From 9636b5e82126705df4efb8f68992ba8dda86b75e Mon Sep 17 00:00:00 2001 From: Ishank gulati Date: Tue, 22 Dec 2015 15:47:11 +0530 Subject: [PATCH 001/153] reduce k_fold parameter --- modules/ml/src/svm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 757bb7a171..e6f2dc9c87 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1442,7 +1442,7 @@ public: //check that while cross-validation there were the samples from all the classes if( class_ranges[class_count] <= 0 ) CV_Error( CV_StsBadArg, "While cross-validation one or more of the classes have " - "been fell out of the sample. Try to enlarge " ); + "been fell out of the sample. Try to reduce " ); if( svmType == NU_SVC ) { From 25b044e6c3b0ac950497cc5838c684d797aefb01 Mon Sep 17 00:00:00 2001 From: Teng Cao Date: Thu, 24 Dec 2015 10:26:42 +0800 Subject: [PATCH 002/153] fix a bug in updateTrainingSet In case fillPassedSamples find zero passed negatives and leafFA is achieved, function updateTrainingSet will return false and print misleading information, this PR fix the case. --- apps/traincascade/cascadeclassifier.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/traincascade/cascadeclassifier.cpp b/apps/traincascade/cascadeclassifier.cpp index 2924fe341f..176cefe7da 100644 --- a/apps/traincascade/cascadeclassifier.cpp +++ b/apps/traincascade/cascadeclassifier.cpp @@ -309,7 +309,8 @@ bool CvCascadeClassifier::updateTrainingSet( double minimumAcceptanceRatio, doub int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible int negCount = fillPassedSamples( posCount, proNumNeg, false, minimumAcceptanceRatio, negConsumed ); if ( !negCount ) - return false; + if ( !(negConsumed > 0 && ((double)negCount+1)/(double)negConsumed <= minimumAcceptanceRatio) ) + return false; curNumSamples = posCount + negCount; acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed ); From 1b5352688f3646b0721e5973ce727238c0ae3d3e Mon Sep 17 00:00:00 2001 From: thierry Date: Fri, 15 Jan 2016 17:35:10 +0100 Subject: [PATCH 003/153] better png transparency handling --- modules/imgcodecs/src/grfmt_png.cpp | 27 ++++++++++++++++----------- modules/imgcodecs/src/loadsave.cpp | 5 ----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 2f4a62baee..e75f0bf45f 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -187,15 +187,12 @@ bool PngDecoder::readHeader() if( bit_depth <= 8 || bit_depth == 16 ) { + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); switch(color_type) { case PNG_COLOR_TYPE_RGB: - m_type = CV_8UC3; - break; case PNG_COLOR_TYPE_PALETTE: - png_get_tRNS( png_ptr, info_ptr, &trans, &num_trans, &trans_values); - //Check if there is a transparency value in the palette - if ( num_trans > 0 ) + if( num_trans > 0 ) m_type = CV_8UC4; else m_type = CV_8UC3; @@ -203,8 +200,14 @@ bool PngDecoder::readHeader() case PNG_COLOR_TYPE_RGB_ALPHA: m_type = CV_8UC4; break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + m_type = CV_8UC2; + break; default: - m_type = CV_8UC1; + if( num_trans > 0 ) + m_type = CV_8UC2; + else + m_type = CV_8UC1; } if( bit_depth == 16 ) m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); @@ -227,7 +230,7 @@ bool PngDecoder::readData( Mat& img ) volatile bool result = false; AutoBuffer _buffer(m_height); uchar** buffer = _buffer; - int color = img.channels() > 1; + int color = img.channels() > 2; uchar* data = img.ptr(); int step = (int)img.step; @@ -246,7 +249,7 @@ bool PngDecoder::readData( Mat& img ) else if( !isBigEndian() ) png_set_swap( png_ptr ); - if(img.channels() < 4) + if(img.channels() != 4 && img.channels() != 2) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png @@ -257,12 +260,13 @@ bool PngDecoder::readData( Mat& img ) * stripping alpha.. 18.11.2004 Axel Walthelm */ png_set_strip_alpha( png_ptr ); - } + } else + png_set_tRNS_to_alpha( png_ptr ); if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); - if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) != 0 && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); @@ -270,7 +274,7 @@ bool PngDecoder::readData( Mat& img ) png_set_gray_1_2_4_to_8( png_ptr ); #endif - if( CV_MAT_CN(m_type) > 1 && color ) + if( CV_MAT_CN(m_type) > 2 && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB @@ -410,6 +414,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16, channels == 1 ? PNG_COLOR_TYPE_GRAY : + channels == 2 ? PNG_COLOR_TYPE_GRAY_ALPHA : channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 70a31c37a2..e0080bd3b9 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -452,8 +452,6 @@ static bool imwrite_( const String& filename, const Mat& image, Mat temp; const Mat* pimage = ℑ - CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 ); - ImageEncoder encoder = findEncoder( filename ); if( !encoder ) CV_Error( CV_StsError, "could not find a writer for the specified extension" ); @@ -590,9 +588,6 @@ bool imencode( const String& ext, InputArray _image, { Mat image = _image.getMat(); - int channels = image.channels(); - CV_Assert( channels == 1 || channels == 3 || channels == 4 ); - ImageEncoder encoder = findEncoder( ext ); if( !encoder ) CV_Error( CV_StsError, "could not find encoder for the specified extension" ); From bdb9cf4d476a3d11956dc058ee114f0dd0718406 Mon Sep 17 00:00:00 2001 From: thierry Date: Mon, 18 Jan 2016 17:56:26 +0100 Subject: [PATCH 004/153] fix inversed grayscale conditional --- modules/imgcodecs/src/grfmt_png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index e75f0bf45f..5b33c66484 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -266,7 +266,7 @@ bool PngDecoder::readData( Mat& img ) if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); - if( (m_color_type & PNG_COLOR_MASK_COLOR) != 0 && m_bit_depth < 8 ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) == 0 && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); From be4312ec3dc7c36f4799a6955f7f6e5b9786a439 Mon Sep 17 00:00:00 2001 From: alcinos Date: Wed, 27 Jan 2016 15:36:23 +0100 Subject: [PATCH 005/153] Wrap DenseOptFlow class around Farneback optical flow computation --- modules/cudaoptflow/src/farneback.cpp | 4 +- .../video/include/opencv2/video/tracking.hpp | 40 +++ modules/video/src/optflowgf.cpp | 233 ++++++++++-------- 3 files changed, 173 insertions(+), 104 deletions(-) diff --git a/modules/cudaoptflow/src/farneback.cpp b/modules/cudaoptflow/src/farneback.cpp index fb62df6864..43032b4f8f 100644 --- a/modules/cudaoptflow/src/farneback.cpp +++ b/modules/cudaoptflow/src/farneback.cpp @@ -93,7 +93,7 @@ namespace cv { namespace cuda { namespace device { namespace optflow_farneback namespace { - class FarnebackOpticalFlowImpl : public FarnebackOpticalFlow + class FarnebackOpticalFlowImpl : public cv::cuda::FarnebackOpticalFlow { public: FarnebackOpticalFlowImpl(int numLevels, double pyrScale, bool fastPyramids, int winSize, @@ -459,7 +459,7 @@ namespace } } -Ptr cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize, +Ptr cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize, int numIters, int polyN, double polySigma, int flags) { return makePtr(numLevels, pyrScale, fastPyramids, winSize, diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index d6954fecca..5afe209ce6 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -508,6 +508,46 @@ public: */ CV_EXPORTS_W Ptr createOptFlow_DualTVL1(); +/** @brief Class computing a dense optical flow using the Gunnar Farneback’s algorithm. + */ +class CV_EXPORTS_W FarnebackOpticalFlow : public DenseOpticalFlow +{ +public: + virtual int getNumLevels() const = 0; + virtual void setNumLevels(int numLevels) = 0; + + virtual double getPyrScale() const = 0; + virtual void setPyrScale(double pyrScale) = 0; + + virtual bool getFastPyramids() const = 0; + virtual void setFastPyramids(bool fastPyramids) = 0; + + virtual int getWinSize() const = 0; + virtual void setWinSize(int winSize) = 0; + + virtual int getNumIters() const = 0; + virtual void setNumIters(int numIters) = 0; + + virtual int getPolyN() const = 0; + virtual void setPolyN(int polyN) = 0; + + virtual double getPolySigma() const = 0; + virtual void setPolySigma(double polySigma) = 0; + + virtual int getFlags() const = 0; + virtual void setFlags(int flags) = 0; + + static Ptr create( + int numLevels = 5, + double pyrScale = 0.5, + bool fastPyramids = false, + int winSize = 13, + int numIters = 10, + int polyN = 5, + double polySigma = 1.1, + int flags = 0); +}; + //! @} video_track } // cv diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 3b61bb24bf..b486edaf84 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -583,39 +583,63 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1, } -#ifdef HAVE_OPENCL namespace cv { -class FarnebackOpticalFlow +namespace +{ +class FarnebackOpticalFlowImpl : public FarnebackOpticalFlow { public: - FarnebackOpticalFlow() + FarnebackOpticalFlowImpl(int numLevels=5, double pyrScale=0.5, bool fastPyramids=false, int winSize=13, + int numIters=10, int polyN=5, double polySigma=1.1, int flags=0) : + numLevels_(numLevels), pyrScale_(pyrScale), fastPyramids_(fastPyramids), winSize_(winSize), + numIters_(numIters), polyN_(polyN), polySigma_(polySigma), flags_(flags) { - numLevels = 5; - pyrScale = 0.5; - fastPyramids = false; - winSize = 13; - numIters = 10; - polyN = 5; - polySigma = 1.1; - flags = 0; } - int numLevels; - double pyrScale; - bool fastPyramids; - int winSize; - int numIters; - int polyN; - double polySigma; - int flags; + virtual int getNumLevels() const { return numLevels_; } + virtual void setNumLevels(int numLevels) { numLevels_ = numLevels; } + virtual double getPyrScale() const { return pyrScale_; } + virtual void setPyrScale(double pyrScale) { pyrScale_ = pyrScale; } + + virtual bool getFastPyramids() const { return fastPyramids_; } + virtual void setFastPyramids(bool fastPyramids) { fastPyramids_ = fastPyramids; } + + virtual int getWinSize() const { return winSize_; } + virtual void setWinSize(int winSize) { winSize_ = winSize; } + + virtual int getNumIters() const { return numIters_; } + virtual void setNumIters(int numIters) { numIters_ = numIters; } + + virtual int getPolyN() const { return polyN_; } + virtual void setPolyN(int polyN) { polyN_ = polyN; } + + virtual double getPolySigma() const { return polySigma_; } + virtual void setPolySigma(double polySigma) { polySigma_ = polySigma; } + + virtual int getFlags() const { return flags_; } + virtual void setFlags(int flags) { flags_ = flags; } + + virtual void calc(InputArray I0, InputArray I1, InputOutputArray flow); + +private: + int numLevels_; + double pyrScale_; + bool fastPyramids_; + int winSize_; + int numIters_; + int polyN_; + double polySigma_; + int flags_; + +#ifdef HAVE_OPENCL bool operator ()(const UMat &frame0, const UMat &frame1, UMat &flowx, UMat &flowy) { CV_Assert(frame0.channels() == 1 && frame1.channels() == 1); CV_Assert(frame0.size() == frame1.size()); - CV_Assert(polyN == 5 || polyN == 7); - CV_Assert(!fastPyramids || std::abs(pyrScale - 0.5) < 1e-6); + CV_Assert(polyN_ == 5 || polyN_ == 7); + CV_Assert(!fastPyramids_ || std::abs(pyrScale_ - 0.5) < 1e-6); const int min_size = 32; @@ -630,9 +654,9 @@ public: // Crop unnecessary levels double scale = 1; int numLevelsCropped = 0; - for (; numLevelsCropped < numLevels; numLevelsCropped++) + for (; numLevelsCropped < numLevels_; numLevelsCropped++) { - scale *= pyrScale; + scale *= pyrScale_; if (size.width*scale < min_size || size.height*scale < min_size) break; } @@ -640,7 +664,7 @@ public: frame0.convertTo(frames_[0], CV_32F); frame1.convertTo(frames_[1], CV_32F); - if (fastPyramids) + if (fastPyramids_) { // Build Gaussian pyramids using pyrDown() pyramid0_.resize(numLevelsCropped + 1); @@ -654,13 +678,13 @@ public: } } - setPolynomialExpansionConsts(polyN, polySigma); + setPolynomialExpansionConsts(polyN_, polySigma_); for (int k = numLevelsCropped; k >= 0; k--) { scale = 1; for (int i = 0; i < k; i++) - scale *= pyrScale; + scale *= pyrScale_; double sigma = (1./scale - 1) * 0.5; int smoothSize = cvRound(sigma*5) | 1; @@ -669,7 +693,7 @@ public: int width = cvRound(size.width*scale); int height = cvRound(size.height*scale); - if (fastPyramids) + if (fastPyramids_) { width = pyramid0_[k].cols; height = pyramid0_[k].rows; @@ -688,7 +712,7 @@ public: if (prevFlowX.empty()) { - if (flags & cv::OPTFLOW_USE_INITIAL_FLOW) + if (flags_ & cv::OPTFLOW_USE_INITIAL_FLOW) { resize(flowx0, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); resize(flowy0, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); @@ -705,8 +729,8 @@ public: { resize(prevFlowX, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); resize(prevFlowY, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); - multiply(1./pyrScale, curFlowX, curFlowX); - multiply(1./pyrScale, curFlowY, curFlowY); + multiply(1./pyrScale_, curFlowX, curFlowX); + multiply(1./pyrScale_, curFlowY, curFlowY); } UMat M = allocMatFromBuf(5*height, width, CV_32F, M_); @@ -717,7 +741,7 @@ public: allocMatFromBuf(5*height, width, CV_32F, R_[1]) }; - if (fastPyramids) + if (fastPyramids_) { if (!polynomialExpansionOcl(pyramid0_[k], R[0])) return false; @@ -752,18 +776,18 @@ public: if (!updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M)) return false; - if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) - setGaussianBlurKernel(winSize, winSize/2*0.3f); - for (int i = 0; i < numIters; i++) + if (flags_ & OPTFLOW_FARNEBACK_GAUSSIAN) + setGaussianBlurKernel(winSize_, winSize_/2*0.3f); + for (int i = 0; i < numIters_; i++) { - if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) + if (flags_ & OPTFLOW_FARNEBACK_GAUSSIAN) { - if (!updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1)) + if (!updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize_, i < numIters_-1)) return false; } else { - if (!updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1)) + if (!updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize_, i < numIters_-1)) return false; } } @@ -776,7 +800,9 @@ public: flowy = curFlowY; return true; } - + virtual void collectGarbage(){ + releaseMemory(); + } void releaseMemory() { frames_[0].release(); @@ -898,15 +924,15 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN) * localsize[0], (size_t)src.rows}; + size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN_) * localsize[0], (size_t)src.rows}; #if 0 const cv::ocl::Device &device = cv::ocl::Device::getDefault(); bool useDouble = (0 != device.doubleFPConfig()); - cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN, useDouble ? 1 : 0); + cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN_, useDouble ? 1 : 0); #else - cv::String build_options = cv::format("-D polyN=%d", polyN); + cv::String build_options = cv::format("-D polyN=%d", polyN_); #endif ocl::Kernel kernel; if (!kernel.create("polynomialExpansion", cv::ocl::video::optical_flow_farneback_oclsrc, build_options)) @@ -1036,60 +1062,43 @@ private: return false; return true; } + bool calc_ocl( InputArray _prev0, InputArray _next0, + InputOutputArray _flow0) + { + if ((5 != polyN_) && (7 != polyN_)) + return false; + if (_next0.size() != _prev0.size()) + return false; + int typePrev = _prev0.type(); + int typeNext = _next0.type(); + if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext))) + return false; + + std::vector flowar; + if (!_flow0.empty()) + split(_flow0, flowar); + else + { + flowar.push_back(UMat()); + flowar.push_back(UMat()); + } + if(!this->operator()(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1])){ + return false; + } + merge(flowar, _flow0); + return true; + } +#else // HAVE_OPENCL + virtual void collectGarbage(){} +#endif }; -static bool ocl_calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, - InputOutputArray _flow0, double pyr_scale, int levels, int winsize, - int iterations, int poly_n, double poly_sigma, int flags ) +void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0, + InputOutputArray _flow0) { - if ((5 != poly_n) && (7 != poly_n)) - return false; - if (_next0.size() != _prev0.size()) - return false; - int typePrev = _prev0.type(); - int typeNext = _next0.type(); - if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext))) - return false; - - FarnebackOpticalFlow opticalFlow; - opticalFlow.numLevels = levels; - opticalFlow.pyrScale = pyr_scale; - opticalFlow.fastPyramids= false; - opticalFlow.winSize = winsize; - opticalFlow.numIters = iterations; - opticalFlow.polyN = poly_n; - opticalFlow.polySigma = poly_sigma; - opticalFlow.flags = flags; - - std::vector flowar; - if (!_flow0.empty()) - split(_flow0, flowar); - else - { - flowar.push_back(UMat()); - flowar.push_back(UMat()); - } - if (!opticalFlow(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1])) - return false; - merge(flowar, _flow0); - return true; -} -} -#endif // HAVE_OPENCL - -void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, - InputOutputArray _flow0, double pyr_scale, int levels, int winsize, - int iterations, int poly_n, double poly_sigma, int flags ) -{ -#ifdef HAVE_OPENCL - bool use_opencl = ocl::useOpenCL() && _flow0.isUMat(); - if( use_opencl && ocl_calcOpticalFlowFarneback(_prev0, _next0, _flow0, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags)) - { - CV_IMPL_ADD(CV_IMPL_OCL); - return; - } -#endif - + CV_OCL_RUN(_flow0.isUMat() && + ocl::Image2D::isFormatSupported(CV_32F, 1, false), + calc_ocl(_prev0,_next0,_flow0)) Mat prev0 = _prev0.getMat(), next0 = _next0.getMat(); const int min_size = 32; const Mat* img[2] = { &prev0, &next0 }; @@ -1097,15 +1106,16 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, int i, k; double scale; Mat prevFlow, flow, fimg; + int levels = numLevels_; CV_Assert( prev0.size() == next0.size() && prev0.channels() == next0.channels() && - prev0.channels() == 1 && pyr_scale < 1 ); + prev0.channels() == 1 && pyrScale_ < 1 ); _flow0.create( prev0.size(), CV_32FC2 ); Mat flow0 = _flow0.getMat(); for( k = 0, scale = 1; k < levels; k++ ) { - scale *= pyr_scale; + scale *= pyrScale_; if( prev0.cols*scale < min_size || prev0.rows*scale < min_size ) break; } @@ -1115,7 +1125,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, for( k = levels; k >= 0; k-- ) { for( i = 0, scale = 1; i < k; i++ ) - scale *= pyr_scale; + scale *= pyrScale_; double sigma = (1./scale-1)*0.5; int smooth_sz = cvRound(sigma*5)|1; @@ -1131,7 +1141,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, if( prevFlow.empty() ) { - if( flags & OPTFLOW_USE_INITIAL_FLOW ) + if( flags_ & OPTFLOW_USE_INITIAL_FLOW ) { resize( flow0, flow, Size(width, height), 0, 0, INTER_AREA ); flow *= scale; @@ -1142,7 +1152,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, else { resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR ); - flow *= 1./pyr_scale; + flow *= 1./pyrScale_; } Mat R[2], I, M; @@ -1151,19 +1161,38 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, img[i]->convertTo(fimg, CV_32F); GaussianBlur(fimg, fimg, Size(smooth_sz, smooth_sz), sigma, sigma); resize( fimg, I, Size(width, height), INTER_LINEAR ); - FarnebackPolyExp( I, R[i], poly_n, poly_sigma ); + FarnebackPolyExp( I, R[i], polyN_, polySigma_ ); } FarnebackUpdateMatrices( R[0], R[1], flow, M, 0, flow.rows ); - for( i = 0; i < iterations; i++ ) + for( i = 0; i < numIters_; i++ ) { - if( flags & OPTFLOW_FARNEBACK_GAUSSIAN ) - FarnebackUpdateFlow_GaussianBlur( R[0], R[1], flow, M, winsize, i < iterations - 1 ); + if( flags_ & OPTFLOW_FARNEBACK_GAUSSIAN ) + FarnebackUpdateFlow_GaussianBlur( R[0], R[1], flow, M, winSize_, i < numIters_ - 1 ); else - FarnebackUpdateFlow_Blur( R[0], R[1], flow, M, winsize, i < iterations - 1 ); + FarnebackUpdateFlow_Blur( R[0], R[1], flow, M, winSize_, i < numIters_ - 1 ); } prevFlow = flow; } } +} // namespace +} // namespace cv + +void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, + InputOutputArray _flow0, double pyr_scale, int levels, int winsize, + int iterations, int poly_n, double poly_sigma, int flags ) +{ + Ptr optflow; + optflow = makePtr(levels,pyr_scale,false,winsize,iterations,poly_n,poly_sigma,flags); + optflow->calc(_prev0,_next0,_flow0); +} + + +cv::Ptr cv::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize, + int numIters, int polyN, double polySigma, int flags) +{ + return makePtr(numLevels, pyrScale, fastPyramids, winSize, + numIters, polyN, polySigma, flags); +} From 6e3b90de9b12c02e6be93f0f3cde01769cd5078a Mon Sep 17 00:00:00 2001 From: alcinos Date: Thu, 28 Jan 2016 16:26:11 +0100 Subject: [PATCH 006/153] Add static creator for TVL1 optical flow class --- modules/core/include/opencv2/core/ptr.inl.hpp | 11 ++++++++++ .../video/include/opencv2/video/tracking.hpp | 15 +++++++++++++ modules/video/src/tvl1flow.cpp | 21 +++++++++++++++++++ modules/video/test/test_tvl1optflow.cpp | 2 +- samples/cpp/tvl1_optical_flow.cpp | 2 +- 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/ptr.inl.hpp b/modules/core/include/opencv2/core/ptr.inl.hpp index 3f6f214a8f..8c09d93cd8 100644 --- a/modules/core/include/opencv2/core/ptr.inl.hpp +++ b/modules/core/include/opencv2/core/ptr.inl.hpp @@ -358,6 +358,17 @@ Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); } +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11, const A12& a12) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); +} } // namespace cv //! @endcond diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index 5afe209ce6..f0993e5f81 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -502,6 +502,21 @@ public: virtual int getMedianFiltering() const = 0; /** @copybrief getMedianFiltering @see getMedianFiltering */ virtual void setMedianFiltering(int val) = 0; + + /** @brief Creates instance of cv::DualTVL1OpticalFlow*/ + static Ptr create( + double tau = 0.25, + double lambda = 0.15, + double theta = 0.3, + int nscales = 5, + int warps = 5, + double epsilon = 0.01, + int innnerIterations = 30, + int outerIterations = 10, + double scaleStep = 0.8, + double gamma = 0.0, + int medianFiltering = 5, + bool useInitialFlow = false); }; /** @brief Creates instance of cv::DenseOpticalFlow diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index b10dc3f344..c0299e5c95 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -89,6 +89,17 @@ namespace { class OpticalFlowDual_TVL1 : public DualTVL1OpticalFlow { public: + + OpticalFlowDual_TVL1(double tau_, double lambda_, double theta_, int nscales_, int warps_, + double epsilon_, int innerIterations_, int outerIterations_, + double scaleStep_, double gamma_, int medianFiltering_, + bool useInitialFlow_) : + tau(tau_), lambda(lambda_), theta(theta_), gamma(gamma_), nscales(nscales_), + warps(warps_), epsilon(epsilon_), innerIterations(innerIterations_), + outerIterations(outerIterations_), useInitialFlow(useInitialFlow_), + scaleStep(scaleStep_), medianFiltering(medianFiltering_) + { + } OpticalFlowDual_TVL1(); void calc(InputArray I0, InputArray I1, InputOutputArray flow); @@ -1450,3 +1461,13 @@ Ptr cv::createOptFlow_DualTVL1() { return makePtr(); } + +Ptr cv::DualTVL1OpticalFlow::create( + double tau, double lambda, double theta, int nscales, int warps, + double epsilon, int innerIterations, int outerIterations, double scaleStep, + double gamma, int medianFilter, bool useInitialFlow) +{ + return makePtr(tau, lambda, theta, nscales, warps, + epsilon, innerIterations, outerIterations, + scaleStep, gamma, medianFilter, useInitialFlow); +} diff --git a/modules/video/test/test_tvl1optflow.cpp b/modules/video/test/test_tvl1optflow.cpp index e4b80637ec..3976f25599 100644 --- a/modules/video/test/test_tvl1optflow.cpp +++ b/modules/video/test/test_tvl1optflow.cpp @@ -154,7 +154,7 @@ TEST(Video_calcOpticalFlowDual_TVL1, Regression) ASSERT_FALSE(frame2.empty()); Mat_ flow; - Ptr tvl1 = createOptFlow_DualTVL1(); + Ptr tvl1 = cv::DualTVL1OpticalFlow::create(); tvl1->calc(frame1, frame2, flow); diff --git a/samples/cpp/tvl1_optical_flow.cpp b/samples/cpp/tvl1_optical_flow.cpp index 55b5558ebe..95871c7298 100644 --- a/samples/cpp/tvl1_optical_flow.cpp +++ b/samples/cpp/tvl1_optical_flow.cpp @@ -185,7 +185,7 @@ int main(int argc, const char* argv[]) } Mat_ flow; - Ptr tvl1 = createOptFlow_DualTVL1(); + Ptr tvl1 = cv::DualTVL1OpticalFlow::create(); const double start = (double)getTickCount(); tvl1->calc(frame0, frame1, flow); From 9b70c44f009bd06ca599647a96158e08c20db1b5 Mon Sep 17 00:00:00 2001 From: alcinos Date: Thu, 28 Jan 2016 16:55:45 +0100 Subject: [PATCH 007/153] Adding interface for Sparse flow computation --- .../video/include/opencv2/video/tracking.hpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index f0993e5f81..983a0c390d 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -397,6 +397,27 @@ public: CV_WRAP virtual void collectGarbage() = 0; }; +/** @brief Base interface for sparse optical flow algorithms. + */ +class CV_EXPORTS_W SparseOpticalFlow : public Algorithm +{ +public: + /** @brief Calculates a sparse optical flow. + + @param prevImg First input image. + @param nextImg Second input image of the same size and the same type as prevImg. + @param prevPts Vector of 2D points for which the flow needs to be found. + @param nextPts Output vector of 2D points containing the calculated new positions of input features in the second image. + @param status Output status vector. Each element of the vector is set to 1 if the + flow for the corresponding features has been found. Otherwise, it is set to 0. + @param err Optional output vector that contains error response for each point (inverse confidence). + */ + CV_WRAP virtual void calc(InputArray prevImg, InputArray nextImg, + InputArray prevPts, InputOutputArray nextPts, + OutputArray status, + OutputArray err = cv::noArray()) = 0; +}; + /** @brief "Dual TV L1" Optical Flow Algorithm. The class implements the "Dual TV L1" optical flow algorithm described in @cite Zach2007 and @@ -563,6 +584,7 @@ public: int flags = 0); }; + //! @} video_track } // cv From e22b838af8a0078ca472583d76d0244dc9fad455 Mon Sep 17 00:00:00 2001 From: alcinos Date: Thu, 28 Jan 2016 18:45:52 +0100 Subject: [PATCH 008/153] Wrap SparseOptFlow class around PyrLK optical flow computation --- modules/cudaoptflow/src/pyrlk.cpp | 12 +- .../video/include/opencv2/video/tracking.hpp | 34 ++++++ modules/video/src/lkpyramid.cpp | 112 +++++++++++------- 3 files changed, 107 insertions(+), 51 deletions(-) diff --git a/modules/cudaoptflow/src/pyrlk.cpp b/modules/cudaoptflow/src/pyrlk.cpp index dcfd1f66de..c7f706087b 100644 --- a/modules/cudaoptflow/src/pyrlk.cpp +++ b/modules/cudaoptflow/src/pyrlk.cpp @@ -47,9 +47,9 @@ using namespace cv::cuda; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } +Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } -Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } +Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ @@ -283,7 +283,7 @@ namespace vPyr[idx].copyTo(v, stream); } - class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase + class SparsePyrLKOpticalFlowImpl : public cv::cuda::SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase { public: SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) : @@ -366,14 +366,14 @@ namespace }; } -Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) +Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) { return makePtr(winSize, maxLevel, iters, useInitialFlow); } -Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) +Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) { return makePtr(winSize, maxLevel, iters, useInitialFlow); } -#endif /* !defined (HAVE_CUDA) */ \ No newline at end of file +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index 983a0c390d..996e60b2dd 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -585,6 +585,40 @@ public: }; +/** @brief Class used for calculating a sparse optical flow. + +The class can calculate an optical flow for a sparse feature set using the +iterative Lucas-Kanade method with pyramids. + +@sa calcOpticalFlowPyrLK + +*/ +class CV_EXPORTS SparsePyrLKOpticalFlow : public SparseOpticalFlow +{ +public: + virtual Size getWinSize() const = 0; + virtual void setWinSize(Size winSize) = 0; + + virtual int getMaxLevel() const = 0; + virtual void setMaxLevel(int maxLevel) = 0; + + virtual TermCriteria getTermCriteria() const = 0; + virtual void setTermCriteria(TermCriteria& crit) = 0; + + virtual int getFlags() const = 0; + virtual void setFlags(int flags) = 0; + + virtual double getMinEigThreshold() const = 0; + virtual void setMinEigThreshold(double minEigThreshold) = 0; + + static Ptr create( + Size winSize = Size(21, 21), + int maxLevel = 3, TermCriteria crit = + TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), + int flags = 0, + double minEigThreshold = 1e-4); +}; + //! @} video_track } // cv diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 891ae78609..25614d9ced 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -837,10 +837,11 @@ int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Si return maxLevel; } -#ifdef HAVE_OPENCL namespace cv { - class PyrLKOpticalFlow +namespace +{ + class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow { struct dim3 { @@ -848,17 +849,40 @@ namespace cv dim3() : x(0), y(0), z(0) { } }; public: - PyrLKOpticalFlow() + SparsePyrLKOpticalFlowImpl(Size winSize_ = Size(21,21), + int maxLevel_ = 3, + TermCriteria criteria_ = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), + int flags_ = 0, + double minEigThreshold_ = 1e-4) : + winSize(winSize_), maxLevel(maxLevel_), criteria(criteria_), flags(flags_), minEigThreshold(minEigThreshold_) +#ifdef HAVE_OPENCL + , iters(criteria_.maxCount), derivLambda(criteria_.epsilon), useInitialFlow(0 != (flags_ & OPTFLOW_LK_GET_MIN_EIGENVALS)), waveSize(0) +#endif { - winSize = Size(21, 21); - maxLevel = 3; - iters = 30; - derivLambda = 0.5; - useInitialFlow = false; - - waveSize = 0; } + virtual Size getWinSize() const {return winSize;} + virtual void setWinSize(Size winSize_){winSize = winSize_;} + + virtual int getMaxLevel() const {return maxLevel;} + virtual void setMaxLevel(int maxLevel_){maxLevel = maxLevel_;} + + virtual TermCriteria getTermCriteria() const {return criteria;} + virtual void setTermCriteria(TermCriteria& crit_){criteria=crit_;} + + virtual int getFlags() const {return flags; } + virtual void setFlags(int flags_){flags=flags_;} + + virtual double getMinEigThreshold() const {return minEigThreshold;} + virtual void setMinEigThreshold(double minEigThreshold_){minEigThreshold=minEigThreshold_;} + + virtual void calc(InputArray prevImg, InputArray nextImg, + InputArray prevPts, InputOutputArray nextPts, + OutputArray status, + OutputArray err = cv::noArray()); + + private: +#ifdef HAVE_OPENCL bool checkParam() { iters = std::min(std::max(iters, 0), 100); @@ -930,14 +954,17 @@ namespace cv } return true; } +#endif Size winSize; int maxLevel; + TermCriteria criteria; + int flags; + double minEigThreshold; +#ifdef HAVE_OPENCL int iters; double derivLambda; bool useInitialFlow; - - private: int waveSize; bool initWaveSize() { @@ -1017,15 +1044,11 @@ namespace cv { return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); } - }; - static bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, - InputArray _prevPts, InputOutputArray _nextPts, - OutputArray _status, OutputArray _err, - Size winSize, int maxLevel, - TermCriteria criteria, - int flags/*, double minEigThreshold*/ ) + bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, + InputArray _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err) { if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags)) return false; @@ -1045,7 +1068,6 @@ namespace cv if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width)) return false; size_t npoints = _prevPts.total(); - bool useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); if (useInitialFlow) { if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) @@ -1060,14 +1082,7 @@ namespace cv _nextPts.create(_prevPts.size(), _prevPts.type()); } - PyrLKOpticalFlow opticalFlow; - opticalFlow.winSize = winSize; - opticalFlow.maxLevel = maxLevel; - opticalFlow.iters = criteria.maxCount; - opticalFlow.derivLambda = criteria.epsilon; - opticalFlow.useInitialFlow = useInitialFlow; - - if (!opticalFlow.checkParam()) + if (!checkParam()) return false; UMat umatErr; @@ -1082,28 +1097,19 @@ namespace cv _status.create((int)npoints, 1, CV_8UC1); UMat umatNextPts = _nextPts.getUMat(); UMat umatStatus = _status.getUMat(); - return opticalFlow.sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); + return sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); } +#endif }; -#endif -void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, +void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts, - OutputArray _status, OutputArray _err, - Size winSize, int maxLevel, - TermCriteria criteria, - int flags, double minEigThreshold ) + OutputArray _status, OutputArray _err) { -#ifdef HAVE_OPENCL - bool use_opencl = ocl::useOpenCL() && - (_prevImg.isUMat() || _nextImg.isUMat()) && - ocl::Image2D::isFormatSupported(CV_32F, 1, false); - if ( use_opencl && ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags/*, minEigThreshold*/)) - { - CV_IMPL_ADD(CV_IMPL_OCL); - return; - } -#endif + CV_OCL_RUN(ocl::useOpenCL() && + (_prevImg.isUMat() || _nextImg.isUMat()) && + ocl::Image2D::isFormatSupported(CV_32F, 1, false), + ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err)) Mat prevPtsMat = _prevPts.getMat(); const int derivDepth = DataType::depth; @@ -1262,6 +1268,22 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, } } +} // namespace +} // namespace cv +cv::Ptr cv::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, TermCriteria crit, int flags, double minEigThreshold){ + return makePtr(winSize,maxLevel,crit,flags,minEigThreshold); +} +void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, + InputArray _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err, + Size winSize, int maxLevel, + TermCriteria criteria, + int flags, double minEigThreshold ) +{ + Ptr optflow = cv::SparsePyrLKOpticalFlow::create(winSize,maxLevel,criteria,flags,minEigThreshold); + optflow->calc(_prevImg,_nextImg,_prevPts,_nextPts,_status,_err); +} + namespace cv { From 93ff1fb2f21a552c258fc2e9f7973f7d5b159cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D1=83=D0=BD=20=D0=92=D0=B8=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80?= Date: Mon, 28 Mar 2016 15:59:18 +0300 Subject: [PATCH 009/153] Correct image borders and principal point computation in cv::stereoRectify --- modules/calib3d/src/calibration.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index b8f569aeb8..8ff0c2cc8c 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -2289,8 +2289,8 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2, for( i = 0; i < 4; i++ ) { int j = (i<2) ? 0 : 1; - _pts[i].x = (float)((i % 2)*(nx-1)); - _pts[i].y = (float)(j*(ny-1)); + _pts[i].x = (float)((i % 2)*(nx)); + _pts[i].y = (float)(j*(ny)); } cvUndistortPoints( &pts, &pts, A, Dk, 0, 0 ); cvConvertPointsHomogeneous( &pts, &pts_3 ); @@ -2304,8 +2304,8 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2, _a_tmp[1][2]=0.0; cvProjectPoints2( &pts_3, k == 0 ? _R1 : _R2, &Z, &A_tmp, 0, &pts ); CvScalar avg = cvAvg(&pts); - cc_new[k].x = (nx-1)/2 - avg.val[0]; - cc_new[k].y = (ny-1)/2 - avg.val[1]; + cc_new[k].x = (nx)/2 - avg.val[0]; + cc_new[k].y = (ny)/2 - avg.val[1]; } // vertical focal length must be the same for both images to keep the epipolar constraint From b973b73ae749e376879cf72d815cb2e9604744e1 Mon Sep 17 00:00:00 2001 From: Bob Paulin Date: Wed, 20 Apr 2016 21:53:52 -0500 Subject: [PATCH 010/153] Add -maxscale parameter to limit the amount sample images can scale in background images --- apps/createsamples/createsamples.cpp | 13 ++++++++++--- apps/createsamples/utility.cpp | 12 +++++++----- apps/createsamples/utility.hpp | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/createsamples/createsamples.cpp b/apps/createsamples/createsamples.cpp index 9f05e416bd..1660adee44 100644 --- a/apps/createsamples/createsamples.cpp +++ b/apps/createsamples/createsamples.cpp @@ -76,6 +76,7 @@ int main( int argc, char* argv[] ) double scale = 4.0; int width = 24; int height = 24; + double maxscale = -1.0; srand((unsigned int)time(0)); @@ -92,9 +93,10 @@ int main( int argc, char* argv[] ) " [-maxyangle ]\n" " [-maxzangle ]\n" " [-show []]\n" - " [-w ]\n [-h ]\n", + " [-w ]\n [-h ]\n" + " [-maxscale ]\n", argv[0], num, bgcolor, bgthreshold, maxintensitydev, - maxxangle, maxyangle, maxzangle, scale, width, height ); + maxxangle, maxyangle, maxzangle, scale, width, height, maxscale ); return 0; } @@ -172,6 +174,10 @@ int main( int argc, char* argv[] ) { height = atoi( argv[++i] ); } + else if( !strcmp( argv[i], "-maxscale" ) ) + { + maxscale = atof( argv[++i] ); + } } printf( "Info file name: %s\n", ((infoname == NULL) ? nullname : infoname ) ); @@ -194,6 +200,7 @@ int main( int argc, char* argv[] ) } printf( "Width: %d\n", width ); printf( "Height: %d\n", height ); + printf( "Max Scale: %g\n", maxscale); /* determine action */ if( imagename && vecname ) @@ -213,7 +220,7 @@ int main( int argc, char* argv[] ) cvCreateTestSamples( infoname, imagename, bgcolor, bgthreshold, bgfilename, num, invert, maxintensitydev, - maxxangle, maxyangle, maxzangle, showsamples, width, height ); + maxxangle, maxyangle, maxzangle, showsamples, width, height, maxscale); printf( "Done\n" ); } diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index b5834f3e02..ddcc1ebe5c 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -38,7 +38,6 @@ // the use of this software, even if advised of the possibility of such damage. // //M*/ - #include #include @@ -1308,7 +1307,7 @@ void cvCreateTestSamples( const char* infoname, int invert, int maxintensitydev, double maxxangle, double maxyangle, double maxzangle, int showsamples, - int winwidth, int winheight ) + int winwidth, int winheight, double maxscale ) { CvSampleDistortionData data; @@ -1337,7 +1336,6 @@ void cvCreateTestSamples( const char* infoname, int i; int x, y, width, height; float scale; - float maxscale; int inverse; if( showsamples ) @@ -1366,12 +1364,16 @@ void cvCreateTestSamples( const char* infoname, for( i = 0; i < count; i++ ) { icvGetNextFromBackgroundData( cvbgdata, cvbgreader ); - - maxscale = MIN( 0.7F * cvbgreader->src.cols / winwidth, + if( maxscale < 0.0 ) + { + maxscale = MIN( 0.7F * cvbgreader->src.cols / winwidth, 0.7F * cvbgreader->src.rows / winheight ); + } + if( maxscale < 1.0F ) continue; scale = (maxscale - 1.0F) * rand() / RAND_MAX + 1.0F; + width = (int) (scale * winwidth); height = (int) (scale * winheight); x = (int) ((0.1+0.8 * rand()/RAND_MAX) * (cvbgreader->src.cols - width)); diff --git a/apps/createsamples/utility.hpp b/apps/createsamples/utility.hpp index 9367778daf..d04947c9be 100644 --- a/apps/createsamples/utility.hpp +++ b/apps/createsamples/utility.hpp @@ -86,7 +86,7 @@ void cvCreateTestSamples( const char* infoname, int invert, int maxintensitydev, double maxxangle, double maxyangle, double maxzangle, int showsamples, - int winwidth, int winheight ); + int winwidth, int winheight, double maxscale ); /* * cvCreateTrainingSamplesFromInfo From bb8faec885a87836b94d5d7c3ea52c11fd380c9e Mon Sep 17 00:00:00 2001 From: Bob Paulin Date: Thu, 21 Apr 2016 07:47:13 -0500 Subject: [PATCH 011/153] #6443 Cast maxscale from double to float for scale calculation. --- apps/createsamples/utility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index ddcc1ebe5c..cf2bdebbf9 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -1372,7 +1372,7 @@ void cvCreateTestSamples( const char* infoname, if( maxscale < 1.0F ) continue; - scale = (maxscale - 1.0F) * rand() / RAND_MAX + 1.0F; + scale = ((float)maxscale - 1.0F) * rand() / RAND_MAX + 1.0F; width = (int) (scale * winwidth); height = (int) (scale * winheight); From e646f9d2f1b276991a59edf01bc87dcdf28e2b8f Mon Sep 17 00:00:00 2001 From: Han Hu Date: Fri, 20 May 2016 11:45:46 +0800 Subject: [PATCH 012/153] Fix subpixel problem of akaze. This is found in the original akaze repo. Previous sub pixel localization method assumes the coordinate (0, 0) is the up-left corner of the up-left pixel. But as far as I know, opencv uses the center of the up-left corner, in this case it should be done in this way. https://github.com/pablofdezalc/akaze/commit/35aeb83a7142e9ec42419603a094ffc2a1401c05 https://github.com/pablofdezalc/akaze/commit/db3dc22981e856ca8111f2f7fe57d9c2e0286efc --- modules/features2d/src/kaze/AKAZEFeatures.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/features2d/src/kaze/AKAZEFeatures.cpp b/modules/features2d/src/kaze/AKAZEFeatures.cpp index 6f1b610ccf..cc317249a7 100644 --- a/modules/features2d/src/kaze/AKAZEFeatures.cpp +++ b/modules/features2d/src/kaze/AKAZEFeatures.cpp @@ -342,14 +342,14 @@ void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector& kpts) if (is_out == false) { if (is_repeated == false) { - point.pt.x *= ratio; - point.pt.y *= ratio; + point.pt.x = (float)(point.pt.x*ratio + .5*(ratio-1.0)); + point.pt.y = (float)(point.pt.y*ratio + .5*(ratio-1.0)); kpts_aux.push_back(point); npoints++; } else { - point.pt.x *= ratio; - point.pt.y *= ratio; + point.pt.x = (float)(point.pt.x*ratio + .5*(ratio-1.0)); + point.pt.y = (float)(point.pt.y*ratio + .5*(ratio-1.0)); kpts_aux[id_repeated] = point; } } // if is_out @@ -439,8 +439,8 @@ void AKAZEFeatures::Do_Subpixel_Refinement(std::vector& kpts) kpts[i].pt.x = x + dst(0); kpts[i].pt.y = y + dst(1); int power = fastpow(2, evolution_[kpts[i].class_id].octave); - kpts[i].pt.x *= power; - kpts[i].pt.y *= power; + kpts[i].pt.x = (float)(kpts[i].pt.x*power + .5*(power-1)); + kpts[i].pt.y = (float)(kpts[i].pt.y*power + .5*(power-1)); kpts[i].angle = 0.0; // In OpenCV the size of a keypoint its the diameter From b2ad7cd9c018d9acf5e319e3f6a99651c0dca244 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Sat, 21 May 2016 21:31:33 +0900 Subject: [PATCH 013/153] add feature to convert FP32(float) to FP16(half) * check compiler support * check HW support before executing * add test doing round trip conversion from / to FP32 * treat array correctly if size is not multiple of 4 * add declaration to prevent warning * make it possible to enable fp16 on 32bit ARM * let the conversion possible on non-supported HW, too. * add test using both HW and SW implementation --- cmake/OpenCVCompilerOptions.cmake | 8 +- modules/core/include/opencv2/core.hpp | 11 + modules/core/include/opencv2/core/cvdef.h | 15 +- modules/core/src/convert.cpp | 359 ++++++++++++++++++++++ modules/core/src/precomp.hpp | 1 + modules/core/src/system.cpp | 12 +- modules/core/test/test_arithm.cpp | 55 ++++ modules/ts/src/ts_func.cpp | 3 + 8 files changed, 459 insertions(+), 5 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 0dcf7ed263..33dd575243 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -146,8 +146,11 @@ if(CMAKE_COMPILER_IS_GNUCXX) elseif(X86 OR X86_64) add_extra_compiler_option(-mno-sse2) endif() + if(ARM) + add_extra_compiler_option("-mfp16-format=ieee") + endif(ARM) if(ENABLE_NEON) - add_extra_compiler_option("-mfpu=neon") + add_extra_compiler_option("-mfpu=neon-fp16") endif() if(ENABLE_VFPV3 AND NOT ENABLE_NEON) add_extra_compiler_option("-mfpu=vfpv3") @@ -167,6 +170,9 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-mfma) endif() endif() + if((X86 OR X86_64) AND NOT MSVC) + add_extra_compiler_option(-mf16c) + endif((X86 OR X86_64) AND NOT MSVC) # GCC depresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions or AVX equivalence for all SSEx instructions when needed. if(NOT OPENCV_EXTRA_CXX_FLAGS MATCHES "-mavx") diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 0d180f51ad..fa7ab469b2 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -524,6 +524,17 @@ For example: CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst, double alpha = 1, double beta = 0); +/** @brief Converts an array to half precision floating number. + +convertFp16 converts FP32 to FP16 or FP16 to FP32. The input array has to have type of CV_32F or +CV_16S to represent the bit depth. If the input array is neither of them, it'll do nothing. + +@param src input array. +@param dst output array. +@param useHW if possible use HW SIMD instruction to convert +*/ +CV_EXPORTS_W void convertFp16(InputArray src, OutputArray dst, bool useHW = true); + /** @brief Performs a look-up table transform of an array. The function LUT fills the output array with values from the look-up table. Indices of the entries diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index c005914190..42e93118b7 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -112,7 +112,7 @@ #define CV_CPU_SSE4_1 6 #define CV_CPU_SSE4_2 7 #define CV_CPU_POPCNT 8 - +#define CV_CPU_FP16 9 #define CV_CPU_AVX 10 #define CV_CPU_AVX2 11 #define CV_CPU_FMA3 12 @@ -143,7 +143,7 @@ enum CpuFeatures { CPU_SSE4_1 = 6, CPU_SSE4_2 = 7, CPU_POPCNT = 8, - + CPU_FP16 = 9, CPU_AVX = 10, CPU_AVX2 = 11, CPU_FMA3 = 12, @@ -193,6 +193,10 @@ enum CpuFeatures { # endif # define CV_POPCNT 1 # endif +# if defined __F16C__ || (defined _MSC_VER && _MSC_VER >= 1700) +# include +# define CV_FP16 1 +# endif # if defined __AVX__ || (defined _MSC_VER && _MSC_VER >= 1600 && 0) // MS Visual Studio 2010 (2012?) has no macro pre-defined to identify the use of /arch:AVX // See: http://connect.microsoft.com/VisualStudio/feedback/details/605858/arch-avx-should-define-a-predefined-macro-in-x64-and-set-a-unique-value-for-m-ix86-fp-in-win32 @@ -223,6 +227,10 @@ enum CpuFeatures { # define CV_NEON 1 #endif +#if defined __GNUC__ && ((defined (__arm__) && (__ARM_FP & 0x2)) || defined(__aarch64__)) +# define CV_FP16 1 +#endif + #if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__ || defined __ARM_NEON__) && !defined __SOFTFP__ # define CV_VFP 1 #endif @@ -253,6 +261,9 @@ enum CpuFeatures { #ifndef CV_SSE4_2 # define CV_SSE4_2 0 #endif +#ifndef CV_FP16 +# define CV_FP16 0 +#endif #ifndef CV_AVX # define CV_AVX 0 #endif diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index f41bfa105f..4ff9830db8 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4356,6 +4356,283 @@ struct Cvt_SIMD #endif +#if !(defined (__arm__) || defined (__aarch64__)) +// const numbers for floating points format +const unsigned int kShiftSignificand = 13; +const unsigned int kMaskFp16Significand = 0x3ff; +const unsigned int kBiasFp16Exponent = 15; +const unsigned int kBiasFp32Exponent = 127; + +union fp32Int32 +{ + int i; + float f; + struct _fp32Format + { + unsigned int significand : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + } fmt; +}; +#endif + +union fp16Int16 +{ + short i; +#if defined (__arm__) || defined (__aarch64__) + __fp16 h; +#endif + struct _fp16Format + { + unsigned int significand : 10; + unsigned int exponent : 5; + unsigned int sign : 1; + } fmt; +}; + +#if defined (__arm__) || defined (__aarch64__) +static float convertFp16SW(short fp16) +{ + // Fp16 -> Fp32 + fp16Int16 a; + a.i = fp16; + return (float)a.h; +} +#else +static float convertFp16SW(short fp16) +{ + // Fp16 -> Fp32 + fp16Int16 b; + b.i = fp16; + int exponent = b.fmt.exponent - kBiasFp16Exponent; + int significand = b.fmt.significand; + + fp32Int32 a; + a.i = 0; + a.fmt.sign = b.fmt.sign; // sign bit + if( exponent == 16 ) + { + // Inf or NaN + a.i = a.i | 0x7F800000; + if( significand != 0 ) + { + // NaN +#if defined(__x86_64__) || defined(_M_X64) + // 64bit + a.i = a.i | 0x7FC00000; +#endif + a.fmt.significand = a.fmt.significand | (significand << kShiftSignificand); + } + return a.f; + } + else if ( exponent == -15 ) + { + // subnormal in Fp16 + if( significand == 0 ) + { + // zero + return a.f; + } + else + { + int shift = -1; + while( ( significand & 0x400 ) == 0 ) + { + significand = significand << 1; + shift++; + } + significand = significand & kMaskFp16Significand; + exponent -= shift; + } + } + + a.fmt.exponent = (exponent+kBiasFp32Exponent); + a.fmt.significand = significand << kShiftSignificand; + return a.f; +} +#endif + +#if defined (__arm__) || defined (__aarch64__) +static short convertFp16SW(float fp32) +{ + // Fp32 -> Fp16 + fp16Int16 a; + a.h = (__fp16)fp32; + return a.i; +} +#else +static short convertFp16SW(float fp32) +{ + // Fp32 -> Fp16 + fp32Int32 a; + a.f = fp32; + int exponent = a.fmt.exponent - kBiasFp32Exponent; + int significand = a.fmt.significand; + + fp16Int16 result; + result.i = 0; + if( 0x477ff000 <= ( a.i & 0x7fffffff ) ) + { + // Inf in Fp16 + result.i = result.i | 0x7C00; + if( exponent == 128 && significand != 0 ) + { + // NaN + result.i = (short)(result.i | 0x200 | (significand >> kShiftSignificand)); + } + } + else if ( ( a.i & 0x7fffffff ) <= 0x387fe000 ) + { + // subnormal in Fp16 + int fp16Significand = significand | 0x800000; + int bitShift = (-exponent) - 1; + fp16Significand = fp16Significand >> bitShift; + + // special cases to round up + int threshold = 0x8000 + ( ( fp16Significand & 1 ) ? 0 : 1 ); + if( threshold <= ( significand & 0xffff ) ) + { + fp16Significand++; + } + result.i = (short)fp16Significand; + } + else + { + // usual situation + // exponent + result.fmt.exponent = (exponent + kBiasFp16Exponent); + + // significand; + short fp16Significand = (short)(significand >> kShiftSignificand); + result.fmt.significand = fp16Significand; + + // special cases to round up + short lsb10bitsFp32 = (significand & 0x1fff); + short threshold = 0x1000 + ( ( fp16Significand & 0x1 ) ? 0 : 1 ); + if( threshold <= lsb10bitsFp32 ) + { + result.i++; + } + else if ( fp16Significand == 0x3ff && exponent == -15) + { + result.i++; + } + } + + // sign bit + result.fmt.sign = a.fmt.sign; + return result.i; +} +#endif + +template static void +cvtScaleHalfSW_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) +{ + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) + { + for ( int x = 0 ; x < size.width; x ++ ) + { + dst[x] = convertFp16SW(src[x]); + } + } +} + +// template for FP16 HW conversion function +template static void +cvtScaleHalfHW_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) +{ + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) + { + int x = 0; + + for ( ; x < size.width; x++ ) + { + } + } +} + +template<> void +cvtScaleHalfHW_( const float* src, size_t sstep, short* dst, size_t dstep, Size size) +{ + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) + { + int x = 0; + + if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 ) + { +#if CV_FP16 + for ( ; x <= size.width - 4; x += 4) + { +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) + __m128 v_src = _mm_load_ps(src + x); + + __m128i v_dst = _mm_cvtps_ph(v_src, 0); + + _mm_storel_epi64((__m128i *)(dst + x), v_dst); +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) + float32x4_t v_src = *(float32x4_t*)(src + x); + + float16x4_t v_dst = vcvt_f16_f32(v_src); + + *(float16x4_t*)(dst + x) = v_dst; +#endif + } +#endif + } + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } + } +} + +template<> void +cvtScaleHalfHW_( const short* src, size_t sstep, float* dst, size_t dstep, Size size) +{ + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) + { + int x = 0; + + if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 ) + { +#if CV_FP16 + for ( ; x <= size.width - 4; x += 4) + { +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) + __m128i v_src = _mm_loadl_epi64((__m128i*)(src+x)); + + __m128 v_dst = _mm_cvtph_ps(v_src); + + _mm_store_ps((dst + x), v_dst); +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) + float16x4_t v_src = *(float16x4_t*)(src + x); + + float32x4_t v_dst = vcvt_f32_f16(v_src); + + *(float32x4_t*)(dst + x) = v_dst; +#endif + } +#endif + } + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } + } +} + template static void cvt_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size ) @@ -4443,6 +4720,13 @@ static void cvtScaleAbs##suffix( const stype* src, size_t sstep, const uchar*, s tfunc(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \ } +#define DEF_CVT_SCALE_FP16_FUNC(suffix, stype, dtype, resource) \ +static void cvtScaleHalf##suffix##resource( const stype* src, size_t sstep, const uchar*, size_t, \ +dtype* dst, size_t dstep, Size size, double*) \ +{ \ + cvtScaleHalf##resource##_(src, sstep, dst, dstep, size); \ +} + #define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \ static void cvtScale##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ dtype* dst, size_t dstep, Size size, double* scale) \ @@ -4499,6 +4783,11 @@ DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float) DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float) DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float) +DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short, SW) +DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float, SW) +DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short, HW) +DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float, HW) + DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float) DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float) DEF_CVT_SCALE_FUNC(16u8u, ushort, uchar, float) @@ -4620,6 +4909,30 @@ static BinaryFunc getCvtScaleAbsFunc(int depth) return cvtScaleAbsTab[depth]; } +BinaryFunc getConvertFuncFp16(int ddepth, bool useHW) +{ + static BinaryFunc cvtTabHW[] = + { + 0, 0, 0, + (BinaryFunc)(cvtScaleHalf32f16fHW), 0, (BinaryFunc)(cvtScaleHalf16f32fHW), + 0, 0, + }; + static BinaryFunc cvtTabSW[] = + { + 0, 0, 0, + (BinaryFunc)(cvtScaleHalf32f16fSW), 0, (BinaryFunc)(cvtScaleHalf16f32fSW), + 0, 0, + }; + if( useHW == true) + { + return cvtTabHW[CV_MAT_DEPTH(ddepth)]; + } + else + { + return cvtTabSW[CV_MAT_DEPTH(ddepth)]; + } +} + BinaryFunc getConvertFunc(int sdepth, int ddepth) { static BinaryFunc cvtTab[][8] = @@ -4804,6 +5117,52 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl } } +void cv::convertFp16( InputArray _src, OutputArray _dst, bool useHW ) +{ + if ( checkHardwareSupport(CV_CPU_FP16) == false) + { + useHW = false; + } + + Mat src = _src.getMat(); + int ddepth = 0; + + switch( src.depth() ) + { + case CV_32F: + ddepth = CV_16S; + break; + case CV_16S: + ddepth = CV_32F; + break; + default: + return; + } + + int type = CV_MAKETYPE(ddepth, src.channels()); + _dst.create( src.dims, src.size, type ); + Mat dst = _dst.getMat(); + BinaryFunc func = getConvertFuncFp16(ddepth, useHW); + int cn = src.channels(); + CV_Assert( func != 0 ); + + if( src.dims <= 2 ) + { + Size sz = getContinuousSize(src, dst, cn); + func( src.data, src.step, 0, 0, dst.data, dst.step, sz, 0); + } + else + { + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + Size sz((int)(it.size*cn), 1); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], 1, 0, 0, ptrs[1], 1, sz, 0); + } +} + void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON; diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index f699ede392..cece96cb08 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -135,6 +135,7 @@ typedef void (*BinaryFuncC)(const uchar* src1, size_t step1, uchar* dst, size_t step, int width, int height, void*); +BinaryFunc getConvertFuncFp16(int ddepth, bool useHW); BinaryFunc getConvertFunc(int sdepth, int ddepth); BinaryFunc getCopyMaskFunc(size_t esz); diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 768280e1a6..a3858c1d19 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -291,6 +291,7 @@ struct HWFeatures f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0; f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0; f.have[CV_CPU_AVX] = (((cpuid_data[2] & (1<<28)) != 0)&&((cpuid_data[2] & (1<<27)) != 0));//OS uses XSAVE_XRSTORE and CPU support AVX + f.have[CV_CPU_FP16] = (cpuid_data[2] & (1<<29)) != 0; // make the second call to the cpuid command in order to get // information about extended features like AVX2 @@ -338,7 +339,8 @@ struct HWFeatures #if defined ANDROID || defined __linux__ #ifdef __aarch64__ f.have[CV_CPU_NEON] = true; - #else + f.have[CV_CPU_FP16] = true; + #elif defined __arm__ int cpufile = open("/proc/self/auxv", O_RDONLY); if (cpufile >= 0) @@ -351,6 +353,7 @@ struct HWFeatures if (auxv.a_type == AT_HWCAP) { f.have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0; + f.have[CV_CPU_FP16] = (auxv.a_un.a_val & 2) != 0; break; } } @@ -358,8 +361,13 @@ struct HWFeatures close(cpufile); } #endif - #elif (defined __clang__ || defined __APPLE__) && (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__)) + #elif (defined __clang__ || defined __APPLE__) + #if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__)) f.have[CV_CPU_NEON] = true; + #endif + #if (defined __ARM_FP && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__)) + f.have[CV_CPU_FP16] = true; + #endif #endif return f; diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index ace7950a64..58974a8f5c 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -737,6 +737,60 @@ struct ConvertScaleOp : public BaseElemWiseOp int ddepth; }; +struct ConvertScaleFp16Op : public BaseElemWiseOp +{ + ConvertScaleFp16Op() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), nextRange(0) { } + void op(const vector& src, Mat& dst, const Mat&) + { + convertFp16(src[0], dst, true); + } + void refop(const vector& src, Mat& dst, const Mat&) + { + convertFp16(src[0], dst, false); + } + int getRandomType(RNG&) + { + // 0: FP32 -> FP16 + // 1: FP16 -> FP32 + int srctype = (nextRange & 1) == 0 ? CV_32F : CV_16S; + return srctype; + } + void getValueRange(int, double& minval, double& maxval) + { + // 0: FP32 -> FP16 + // 1: FP16 -> FP32 + if( (nextRange & 1) == 0 ) + { + // largest integer number that fp16 can express + maxval = 65504.f; + minval = -maxval; + } + else + { + // 0: positive number range + // 1: negative number range + if( (nextRange & 2) == 0 ) + { + minval = 0; // 0x0000 +0 + maxval = 31744; // 0x7C00 +Inf + } + else + { + minval = -32768; // 0x8000 -0 + maxval = -1024; // 0xFC00 -Inf + } + } + } + double getMaxErr(int) + { + return 0.5f; + } + void generateScalars(int, RNG& rng) + { + nextRange = rng.next(); + } + int nextRange; +}; struct ConvertScaleAbsOp : public BaseElemWiseOp { @@ -1371,6 +1425,7 @@ INSTANTIATE_TEST_CASE_P(Core_Copy, ElemWiseTest, ::testing::Values(ElemWiseOpPtr INSTANTIATE_TEST_CASE_P(Core_Set, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetOp))); INSTANTIATE_TEST_CASE_P(Core_SetZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetZeroOp))); INSTANTIATE_TEST_CASE_P(Core_ConvertScale, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleOp))); +INSTANTIATE_TEST_CASE_P(Core_ConvertScaleFp16, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleFp16Op))); INSTANTIATE_TEST_CASE_P(Core_ConvertScaleAbs, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleAbsOp))); INSTANTIATE_TEST_CASE_P(Core_Add, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddOp))); diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index ca7664cce9..a8f146031e 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -3064,6 +3064,9 @@ void printVersionInfo(bool useStdOut) #if CV_NEON if (checkHardwareSupport(CV_CPU_NEON)) cpu_features += " neon"; #endif +#if CV_FP16 + if (checkHardwareSupport(CV_CPU_FP16)) cpu_features += " fp16"; +#endif cpu_features.erase(0, 1); // erase initial space From 98dce911ca46b192423d595e63c272a6488b6810 Mon Sep 17 00:00:00 2001 From: Susmit Date: Thu, 2 Jun 2016 01:06:17 +0530 Subject: [PATCH 014/153] Update py_calibration.markdown In the camera calibration code { cv2.cornerSubPix() } will be of no use.In the updated code it is assigned to the (corners2) variable which is passed down to { cv2.drawChessboardCorners() } --- .../py_calib3d/py_calibration/py_calibration.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.markdown b/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.markdown index 9c6c1fb643..1e22cedfb0 100644 --- a/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.markdown +++ b/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.markdown @@ -130,11 +130,11 @@ for fname in images: if ret == True: objpoints.append(objp) - cv2.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria) + corners2=cv2.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria) imgpoints.append(corners) # Draw and display the corners - cv2.drawChessboardCorners(img, (7,6), corners, ret) + cv2.drawChessboardCorners(img, (7,6), corners2, ret) cv2.imshow('img', img) cv2.waitKey(500) From cf0df733dad004df3505866a67c1b62474d8cbf0 Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Thu, 2 Jun 2016 10:58:46 +0200 Subject: [PATCH 015/153] Fix houghcircles.py when no circles found In the C++ equivalent of this example a check is made whether the vector (here in Python we have a list) actually has any circles in it that is whether the Hough circles function has managed to find any in the given image. This check is missing for the Python example and if no circles are found the application breaks. --- samples/python/houghcircles.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/samples/python/houghcircles.py b/samples/python/houghcircles.py index 5386fc2102..41d42eb1e1 100755 --- a/samples/python/houghcircles.py +++ b/samples/python/houghcircles.py @@ -29,10 +29,12 @@ if __name__ == '__main__': cimg = src.copy() # numpy function circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30) - a, b, c = circles.shape - for i in range(b): - cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv2.LINE_AA) - cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), 2, (0, 255, 0), 3, cv2.LINE_AA) # draw center of circle + + if circles != None: # Check if circles have been found and only then iterate over these and add them to the image + a, b, c = circles.shape + for i in range(b): + cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv2.LINE_AA) + cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), 2, (0, 255, 0), 3, cv2.LINE_AA) # draw center of circle cv2.imshow("source", src) cv2.imshow("detected circles", cimg) From 14deab252bc50f2f99d0944bce3d80b04450ea1b Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Thu, 2 Jun 2016 11:00:23 +0200 Subject: [PATCH 016/153] Fix houghlines.py when no lines found In the C++ equivalent of this example a check is made whether the vector (here in Python we have a list) actually has any lines in it that is whether the Hough lines function has managed to find any in the given image. This check is missing for the Python example and if no lines are found the application breaks. --- samples/python/houghlines.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/samples/python/houghlines.py b/samples/python/houghlines.py index 120d8bbaae..98c3640147 100755 --- a/samples/python/houghlines.py +++ b/samples/python/houghlines.py @@ -36,16 +36,17 @@ if __name__ == '__main__': else: # HoughLines lines = cv2.HoughLines(dst, 1, math.pi/180.0, 50, np.array([]), 0, 0) - a,b,c = lines.shape - for i in range(a): - rho = lines[i][0][0] - theta = lines[i][0][1] - a = math.cos(theta) - b = math.sin(theta) - x0, y0 = a*rho, b*rho - pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) ) - pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) ) - cv2.line(cdst, pt1, pt2, (0, 0, 255), 3, cv2.LINE_AA) + if lines != None: + a,b,c = lines.shape + for i in range(a): + rho = lines[i][0][0] + theta = lines[i][0][1] + a = math.cos(theta) + b = math.sin(theta) + x0, y0 = a*rho, b*rho + pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) ) + pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) ) + cv2.line(cdst, pt1, pt2, (0, 0, 255), 3, cv2.LINE_AA) cv2.imshow("source", src) cv2.imshow("detected lines", cdst) From d913463932440b7ba56b4bf527887b509b5ca71a Mon Sep 17 00:00:00 2001 From: Susmit Date: Thu, 2 Jun 2016 17:47:45 +0530 Subject: [PATCH 017/153] Terrible bugs in the tutorial code in py_pose.markdown There were two bugs that were solved here.Changes were done after extreme testing. 1.replaced cv2.solvePnPRansac() with cv2.solvePnP() previous fc was giving terrible errors. 2.The code was incapable of saving edited pics;Now fixed with little code mods. --- doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown b/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown index f0d48265c9..0ec22c6297 100644 --- a/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown +++ b/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown @@ -70,15 +70,15 @@ for fname in glob.glob('left*.jpg'): corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria) # Find the rotation and translation vectors. - rvecs, tvecs, inliers = cv2.solvePnPRansac(objp, corners2, mtx, dist) + ret,rvecs, tvecs, inliers = cv2.solvePnP(objp, corners2, mtx, dist) # project 3D points to image plane imgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist) img = draw(img,corners2,imgpts) cv2.imshow('img',img) - k = cv2.waitKey(0) & 0xff - if k == 's': + k = cv2.waitKey(0) & 0xFF + if k == ord('s'): cv2.imwrite(fname[:6]+'.png', img) cv2.destroyAllWindows() From eccf2fa4c3a48832c4b3855fea1674100579e13a Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 6 Jun 2016 08:56:37 +0900 Subject: [PATCH 018/153] follow other interface * remove useHW option * update test --- modules/core/include/opencv2/core.hpp | 2 +- modules/core/src/convert.cpp | 5 +++-- modules/core/test/test_arithm.cpp | 18 ++++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index fa7ab469b2..fef0395fef 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -533,7 +533,7 @@ CV_16S to represent the bit depth. If the input array is neither of them, it'll @param dst output array. @param useHW if possible use HW SIMD instruction to convert */ -CV_EXPORTS_W void convertFp16(InputArray src, OutputArray dst, bool useHW = true); +CV_EXPORTS_W void convertFp16(InputArray src, OutputArray dst); /** @brief Performs a look-up table transform of an array. diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 4ff9830db8..431942fbea 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -5117,9 +5117,10 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl } } -void cv::convertFp16( InputArray _src, OutputArray _dst, bool useHW ) +void cv::convertFp16( InputArray _src, OutputArray _dst) { - if ( checkHardwareSupport(CV_CPU_FP16) == false) + bool useHW = true; + if ( checkHardwareSupport(CV_CPU_FP16) == false ) { useHW = false; } diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 58974a8f5c..3548765295 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -742,27 +742,29 @@ struct ConvertScaleFp16Op : public BaseElemWiseOp ConvertScaleFp16Op() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), nextRange(0) { } void op(const vector& src, Mat& dst, const Mat&) { - convertFp16(src[0], dst, true); + Mat m; + convertFp16(src[0], m); + convertFp16(m, dst); } void refop(const vector& src, Mat& dst, const Mat&) { - convertFp16(src[0], dst, false); + cvtest::copy(src[0], dst); } int getRandomType(RNG&) { - // 0: FP32 -> FP16 - // 1: FP16 -> FP32 + // 0: FP32 -> FP16 -> FP32 + // 1: FP16 -> FP32 -> FP16 int srctype = (nextRange & 1) == 0 ? CV_32F : CV_16S; return srctype; } void getValueRange(int, double& minval, double& maxval) { - // 0: FP32 -> FP16 - // 1: FP16 -> FP32 + // 0: FP32 -> FP16 -> FP32 + // 1: FP16 -> FP32 -> FP16 if( (nextRange & 1) == 0 ) { - // largest integer number that fp16 can express - maxval = 65504.f; + // largest integer number that fp16 can express exactly + maxval = 2048.f; minval = -maxval; } else From 4239bac4edd646e60ee5114c4993bdf5a327a73f Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 6 Jun 2016 18:06:23 +0900 Subject: [PATCH 019/153] fix warning of doc * update the comment to real header --- modules/core/include/opencv2/core.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index fef0395fef..22121cef1c 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -531,7 +531,6 @@ CV_16S to represent the bit depth. If the input array is neither of them, it'll @param src input array. @param dst output array. -@param useHW if possible use HW SIMD instruction to convert */ CV_EXPORTS_W void convertFp16(InputArray src, OutputArray dst); From 15f8bc6f37d4e4f882b3a090da0179742b3e6dd0 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 6 Jun 2016 18:49:12 +0900 Subject: [PATCH 020/153] fix cmake * enable fp16 feature correctly with gcc on x86/x86_64 --- cmake/OpenCVCompilerOptions.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 33dd575243..8b2b54f81e 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -170,9 +170,6 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-mfma) endif() endif() - if((X86 OR X86_64) AND NOT MSVC) - add_extra_compiler_option(-mf16c) - endif((X86 OR X86_64) AND NOT MSVC) # GCC depresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions or AVX equivalence for all SSEx instructions when needed. if(NOT OPENCV_EXTRA_CXX_FLAGS MATCHES "-mavx") @@ -204,6 +201,9 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-mpopcnt) endif() endif() + if((X86 OR X86_64) AND NOT MSVC) + add_extra_compiler_option(-mf16c) + endif((X86 OR X86_64) AND NOT MSVC) endif(NOT MINGW) if(X86 OR X86_64) From fbfd3158a76d161fd4148a61553218ee1cdb98d4 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 7 Jun 2016 08:59:28 +0900 Subject: [PATCH 021/153] fix corner case when number is small --- modules/core/src/convert.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 431942fbea..432494dd31 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4471,17 +4471,31 @@ static short convertFp16SW(float fp32) fp16Int16 result; result.i = 0; - if( 0x477ff000 <= ( a.i & 0x7fffffff ) ) + unsigned int absolute = a.i & 0x7fffffff; + if( 0x477ff000 <= absolute ) { // Inf in Fp16 result.i = result.i | 0x7C00; if( exponent == 128 && significand != 0 ) { // NaN - result.i = (short)(result.i | 0x200 | (significand >> kShiftSignificand)); + result.i = (short)( result.i | 0x200 | ( significand >> kShiftSignificand ) ); } } - else if ( ( a.i & 0x7fffffff ) <= 0x387fe000 ) + else if ( absolute < 0x33000001 ) + { + // too small for fp16 + result.i = 0; + } + else if ( absolute < 0x33c00000 ) + { + result.i = 1; + } + else if ( absolute < 0x34200001 ) + { + result.i = 2; + } + else if ( absolute < 0x387fe000 ) { // subnormal in Fp16 int fp16Significand = significand | 0x800000; @@ -4489,8 +4503,9 @@ static short convertFp16SW(float fp32) fp16Significand = fp16Significand >> bitShift; // special cases to round up - int threshold = 0x8000 + ( ( fp16Significand & 1 ) ? 0 : 1 ); - if( threshold <= ( significand & 0xffff ) ) + bitShift = exponent + 24; + unsigned int threshold = ( ( 0x400000 >> bitShift ) | ( ( ( significand & ( 0x800000 >> bitShift ) ) >> ( 126 - a.fmt.exponent ) ) ^ 1 ) ); + if( threshold <= ( significand & ( 0xffffff >> ( exponent + 25 ) ) ) ) { fp16Significand++; } @@ -4500,7 +4515,7 @@ static short convertFp16SW(float fp32) { // usual situation // exponent - result.fmt.exponent = (exponent + kBiasFp16Exponent); + result.fmt.exponent = ( exponent + kBiasFp16Exponent ); // significand; short fp16Significand = (short)(significand >> kShiftSignificand); From 6f6eebbcb9471106a7777329a970ac0aed25e24f Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 7 Jun 2016 18:31:18 +0900 Subject: [PATCH 022/153] fix warning --- modules/core/src/convert.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 432494dd31..d44e5eb8cd 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4504,7 +4504,7 @@ static short convertFp16SW(float fp32) // special cases to round up bitShift = exponent + 24; - unsigned int threshold = ( ( 0x400000 >> bitShift ) | ( ( ( significand & ( 0x800000 >> bitShift ) ) >> ( 126 - a.fmt.exponent ) ) ^ 1 ) ); + int threshold = ( ( 0x400000 >> bitShift ) | ( ( ( significand & ( 0x800000 >> bitShift ) ) >> ( 126 - a.fmt.exponent ) ) ^ 1 ) ); if( threshold <= ( significand & ( 0xffffff >> ( exponent + 25 ) ) ) ) { fp16Significand++; From fd76ed5c0f83fec927b5a98bc192af0776a1432d Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 7 Jun 2016 18:32:47 +0900 Subject: [PATCH 023/153] fix to support wider compiler * check compiler more strictly * use gcc version of fp16 conversion if it's possible (gcc 4.7 and later) * use current SW implementation in other cases --- modules/core/src/convert.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index d44e5eb8cd..5e983da3a0 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4356,7 +4356,7 @@ struct Cvt_SIMD #endif -#if !(defined (__arm__) || defined (__aarch64__)) +#if !( ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) ) // const numbers for floating points format const unsigned int kShiftSignificand = 13; const unsigned int kMaskFp16Significand = 0x3ff; @@ -4379,7 +4379,7 @@ union fp32Int32 union fp16Int16 { short i; -#if defined (__arm__) || defined (__aarch64__) +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) __fp16 h; #endif struct _fp16Format @@ -4390,7 +4390,7 @@ union fp16Int16 } fmt; }; -#if defined (__arm__) || defined (__aarch64__) +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) static float convertFp16SW(short fp16) { // Fp16 -> Fp32 @@ -4452,7 +4452,7 @@ static float convertFp16SW(short fp16) } #endif -#if defined (__arm__) || defined (__aarch64__) +#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) static short convertFp16SW(float fp32) { // Fp32 -> Fp16 From d0a83909635bc78343e7fcbfa495e1f07325fa17 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Thu, 9 Jun 2016 08:41:37 +0900 Subject: [PATCH 024/153] fix run time error on Mac * integrate HW version and SW version to same function --- modules/core/src/convert.cpp | 150 +++++++++++++++++------------------ 1 file changed, 71 insertions(+), 79 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 5e983da3a0..dc41eff37a 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4540,24 +4540,9 @@ static short convertFp16SW(float fp32) } #endif -template static void -cvtScaleHalfSW_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) -{ - sstep /= sizeof(src[0]); - dstep /= sizeof(dst[0]); - - for( ; size.height--; src += sstep, dst += dstep ) - { - for ( int x = 0 ; x < size.width; x ++ ) - { - dst[x] = convertFp16SW(src[x]); - } - } -} - // template for FP16 HW conversion function template static void -cvtScaleHalfHW_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) +cvtScaleHalf_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) { sstep /= sizeof(src[0]); dstep /= sizeof(dst[0]); @@ -4573,77 +4558,105 @@ cvtScaleHalfHW_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size) } template<> void -cvtScaleHalfHW_( const float* src, size_t sstep, short* dst, size_t dstep, Size size) +cvtScaleHalf_( const float* src, size_t sstep, short* dst, size_t dstep, Size size) { sstep /= sizeof(src[0]); dstep /= sizeof(dst[0]); - for( ; size.height--; src += sstep, dst += dstep ) + if( checkHardwareSupport(CV_FP16) ) { - int x = 0; - - if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 ) + for( ; size.height--; src += sstep, dst += dstep ) { -#if CV_FP16 - for ( ; x <= size.width - 4; x += 4) + int x = 0; + + if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 ) { +#if CV_FP16 + for ( ; x <= size.width - 4; x += 4) + { #if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) - __m128 v_src = _mm_load_ps(src + x); + __m128 v_src = _mm_load_ps(src + x); - __m128i v_dst = _mm_cvtps_ph(v_src, 0); + __m128i v_dst = _mm_cvtps_ph(v_src, 0); - _mm_storel_epi64((__m128i *)(dst + x), v_dst); + _mm_storel_epi64((__m128i *)(dst + x), v_dst); #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) - float32x4_t v_src = *(float32x4_t*)(src + x); + float32x4_t v_src = *(float32x4_t*)(src + x); - float16x4_t v_dst = vcvt_f16_f32(v_src); + float16x4_t v_dst = vcvt_f16_f32(v_src); - *(float16x4_t*)(dst + x) = v_dst; + *(float16x4_t*)(dst + x) = v_dst; +#endif + } #endif } -#endif + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } } - for ( ; x < size.width; x++ ) + } + else + { + for( ; size.height--; src += sstep, dst += dstep ) { - dst[x] = convertFp16SW(src[x]); + int x = 0; + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } } } } template<> void -cvtScaleHalfHW_( const short* src, size_t sstep, float* dst, size_t dstep, Size size) +cvtScaleHalf_( const short* src, size_t sstep, float* dst, size_t dstep, Size size) { sstep /= sizeof(src[0]); dstep /= sizeof(dst[0]); - for( ; size.height--; src += sstep, dst += dstep ) + if( checkHardwareSupport(CV_FP16) ) { - int x = 0; - - if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 ) + for( ; size.height--; src += sstep, dst += dstep ) { -#if CV_FP16 - for ( ; x <= size.width - 4; x += 4) + int x = 0; + + if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 && checkHardwareSupport(CV_CPU_FP16) ) { +#if CV_FP16 + for ( ; x <= size.width - 4; x += 4) + { #if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386) - __m128i v_src = _mm_loadl_epi64((__m128i*)(src+x)); + __m128i v_src = _mm_loadl_epi64((__m128i*)(src+x)); - __m128 v_dst = _mm_cvtph_ps(v_src); + __m128 v_dst = _mm_cvtph_ps(v_src); - _mm_store_ps((dst + x), v_dst); + _mm_store_ps((dst + x), v_dst); #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) - float16x4_t v_src = *(float16x4_t*)(src + x); + float16x4_t v_src = *(float16x4_t*)(src + x); - float32x4_t v_dst = vcvt_f32_f16(v_src); + float32x4_t v_dst = vcvt_f32_f16(v_src); - *(float32x4_t*)(dst + x) = v_dst; + *(float32x4_t*)(dst + x) = v_dst; +#endif + } #endif } -#endif + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } } - for ( ; x < size.width; x++ ) + } + else + { + for( ; size.height--; src += sstep, dst += dstep ) { - dst[x] = convertFp16SW(src[x]); + int x = 0; + for ( ; x < size.width; x++ ) + { + dst[x] = convertFp16SW(src[x]); + } } } } @@ -4735,11 +4748,11 @@ static void cvtScaleAbs##suffix( const stype* src, size_t sstep, const uchar*, s tfunc(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \ } -#define DEF_CVT_SCALE_FP16_FUNC(suffix, stype, dtype, resource) \ -static void cvtScaleHalf##suffix##resource( const stype* src, size_t sstep, const uchar*, size_t, \ +#define DEF_CVT_SCALE_FP16_FUNC(suffix, stype, dtype) \ +static void cvtScaleHalf##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ dtype* dst, size_t dstep, Size size, double*) \ { \ - cvtScaleHalf##resource##_(src, sstep, dst, dstep, size); \ + cvtScaleHalf##_(src, sstep, dst, dstep, size); \ } #define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \ @@ -4798,10 +4811,8 @@ DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float) DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float) DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float) -DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short, SW) -DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float, SW) -DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short, HW) -DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float, HW) +DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short) +DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float) DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float) DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float) @@ -4924,28 +4935,15 @@ static BinaryFunc getCvtScaleAbsFunc(int depth) return cvtScaleAbsTab[depth]; } -BinaryFunc getConvertFuncFp16(int ddepth, bool useHW) +BinaryFunc getConvertFuncFp16(int ddepth) { - static BinaryFunc cvtTabHW[] = + static BinaryFunc cvtTab[] = { 0, 0, 0, - (BinaryFunc)(cvtScaleHalf32f16fHW), 0, (BinaryFunc)(cvtScaleHalf16f32fHW), + (BinaryFunc)(cvtScaleHalf32f16f), 0, (BinaryFunc)(cvtScaleHalf16f32f), 0, 0, }; - static BinaryFunc cvtTabSW[] = - { - 0, 0, 0, - (BinaryFunc)(cvtScaleHalf32f16fSW), 0, (BinaryFunc)(cvtScaleHalf16f32fSW), - 0, 0, - }; - if( useHW == true) - { - return cvtTabHW[CV_MAT_DEPTH(ddepth)]; - } - else - { - return cvtTabSW[CV_MAT_DEPTH(ddepth)]; - } + return cvtTab[CV_MAT_DEPTH(ddepth)]; } BinaryFunc getConvertFunc(int sdepth, int ddepth) @@ -5134,12 +5132,6 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl void cv::convertFp16( InputArray _src, OutputArray _dst) { - bool useHW = true; - if ( checkHardwareSupport(CV_CPU_FP16) == false ) - { - useHW = false; - } - Mat src = _src.getMat(); int ddepth = 0; @@ -5158,7 +5150,7 @@ void cv::convertFp16( InputArray _src, OutputArray _dst) int type = CV_MAKETYPE(ddepth, src.channels()); _dst.create( src.dims, src.size, type ); Mat dst = _dst.getMat(); - BinaryFunc func = getConvertFuncFp16(ddepth, useHW); + BinaryFunc func = getConvertFuncFp16(ddepth); int cn = src.channels(); CV_Assert( func != 0 ); From 25e2e8aa3c22ddbad5a2006ffb654ec28827cb30 Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Thu, 9 Jun 2016 07:18:47 +0200 Subject: [PATCH 025/153] Removed trailing spaces at line 32 --- samples/python/houghcircles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/python/houghcircles.py b/samples/python/houghcircles.py index 41d42eb1e1..477dac00d4 100755 --- a/samples/python/houghcircles.py +++ b/samples/python/houghcircles.py @@ -29,7 +29,7 @@ if __name__ == '__main__': cimg = src.copy() # numpy function circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30) - + if circles != None: # Check if circles have been found and only then iterate over these and add them to the image a, b, c = circles.shape for i in range(b): From 87d0c91dcfe7c5e323e7c98f23a38f81f09358ea Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Thu, 9 Jun 2016 18:24:00 +0900 Subject: [PATCH 026/153] fix warning of build --- modules/core/src/precomp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index cece96cb08..df6c5b93ec 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -135,7 +135,7 @@ typedef void (*BinaryFuncC)(const uchar* src1, size_t step1, uchar* dst, size_t step, int width, int height, void*); -BinaryFunc getConvertFuncFp16(int ddepth, bool useHW); +BinaryFunc getConvertFuncFp16(int ddepth); BinaryFunc getConvertFunc(int sdepth, int ddepth); BinaryFunc getCopyMaskFunc(size_t esz); From c5bbc0353c1daadae8d953baf2940b146cd87185 Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Sun, 12 Jun 2016 12:54:16 +0200 Subject: [PATCH 027/153] Added small fix when circles are not detected I noticed that I missed the fact that `cimg` is used in the second `imshow()` call. Changed the scope of the second function call to be within the if-statement. Otherwise in cases where have not been detected the second `imshow()` will attempt to use `cimg` which will be empty leading to an error. --- samples/python/houghcircles.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/python/houghcircles.py b/samples/python/houghcircles.py index 477dac00d4..0bfee42933 100755 --- a/samples/python/houghcircles.py +++ b/samples/python/houghcircles.py @@ -35,7 +35,8 @@ if __name__ == '__main__': for i in range(b): cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv2.LINE_AA) cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), 2, (0, 255, 0), 3, cv2.LINE_AA) # draw center of circle + + cv2.imshow("detected circles", cimg) cv2.imshow("source", src) - cv2.imshow("detected circles", cimg) cv2.waitKey(0) From 445349dd7d2ab81f2fd027f6f0575277d35882f4 Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Sun, 12 Jun 2016 12:55:29 +0200 Subject: [PATCH 028/153] Same fix as with the houghcircles Moved second `imshow()` inside the if-statement to prevent error when no lines have been found and the function is called with an empty `cdst`. --- samples/python/houghlines.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/python/houghlines.py b/samples/python/houghlines.py index 98c3640147..4a98828824 100755 --- a/samples/python/houghlines.py +++ b/samples/python/houghlines.py @@ -47,7 +47,8 @@ if __name__ == '__main__': pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) ) pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) ) cv2.line(cdst, pt1, pt2, (0, 0, 255), 3, cv2.LINE_AA) + + cv2.imshow("detected lines", cdst) cv2.imshow("source", src) - cv2.imshow("detected lines", cdst) cv2.waitKey(0) From 4fa86dad263bd8c31f40d7b1fcb151ca29c441cd Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Mon, 13 Jun 2016 09:00:29 +0200 Subject: [PATCH 029/153] Update houghcircles.py --- samples/python/houghcircles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/python/houghcircles.py b/samples/python/houghcircles.py index 0bfee42933..41cce29be7 100755 --- a/samples/python/houghcircles.py +++ b/samples/python/houghcircles.py @@ -35,7 +35,7 @@ if __name__ == '__main__': for i in range(b): cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), circles[0][i][2], (0, 0, 255), 3, cv2.LINE_AA) cv2.circle(cimg, (circles[0][i][0], circles[0][i][1]), 2, (0, 255, 0), 3, cv2.LINE_AA) # draw center of circle - + cv2.imshow("detected circles", cimg) cv2.imshow("source", src) From 0637ca21dcc91bb2ebb6f26530107dc2b49693bf Mon Sep 17 00:00:00 2001 From: Aleksandar Atanasov Date: Mon, 13 Jun 2016 09:00:42 +0200 Subject: [PATCH 030/153] Update houghlines.py --- samples/python/houghlines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/python/houghlines.py b/samples/python/houghlines.py index 4a98828824..445068aef4 100755 --- a/samples/python/houghlines.py +++ b/samples/python/houghlines.py @@ -47,7 +47,7 @@ if __name__ == '__main__': pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) ) pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) ) cv2.line(cdst, pt1, pt2, (0, 0, 255), 3, cv2.LINE_AA) - + cv2.imshow("detected lines", cdst) cv2.imshow("source", src) From addb15383a2780f177b80fed51bdf7724fe0a24a Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 15 Jun 2016 18:02:41 +0900 Subject: [PATCH 031/153] fix run time error --- cmake/OpenCVCompilerOptions.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 8b2b54f81e..db4b239f0b 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -201,9 +201,9 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-mpopcnt) endif() endif() - if((X86 OR X86_64) AND NOT MSVC) + if((X86 OR X86_64) AND NOT MSVC AND NOT APPLE) add_extra_compiler_option(-mf16c) - endif((X86 OR X86_64) AND NOT MSVC) + endif((X86 OR X86_64) AND NOT MSVC AND NOT APPLE) endif(NOT MINGW) if(X86 OR X86_64) From 6020dacc11d5b3719ffa0189a33ddbb1f6ce01d6 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sat, 25 Jun 2016 00:09:50 +0300 Subject: [PATCH 032/153] highgui module: implemented QT and GTK mouse wheel callback support in linux --- modules/highgui/src/window_QT.cpp | 12 +++++++++++- modules/highgui/src/window_QT.h | 2 +- modules/highgui/src/window_gtk.cpp | 29 +++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 925bc222d4..30f99d7708 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -2629,8 +2629,18 @@ void DefaultViewPort::resizeEvent(QResizeEvent* evnt) void DefaultViewPort::wheelEvent(QWheelEvent* evnt) { - scaleView(evnt->delta() / 240.0, evnt->pos()); + int delta = evnt->delta(); + int cv_event = -1; + int flags = ((delta & 0xffff)<<16) | ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + QPoint pt = evnt->pos(); + + icvmouseHandler(evnt, mouse_wheel, cv_event, flags); + icvmouseProcessing(QPoingF(pt), cv_event, flags); + + scaleView(evnt->delta() / 240.0, pt); viewport()->update(); + + QWidget::mouseWheel(evnt); } diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index c0769dcc94..7896b9f4d0 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -366,7 +366,7 @@ private slots: }; -enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3 }; +enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3, mouse_wheel = 3 }; static const int tableMouseButtons[][3]={ {CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP}, //mouse_up {CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN}, //mouse_down diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 29172e72d1..928118e225 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1066,6 +1066,8 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) G_CALLBACK(icvOnMouse), window ); g_signal_connect( window->widget, "motion-notify-event", G_CALLBACK(icvOnMouse), window ); + g_signal_connect( window->widget, "scroll-event", + G_CALLBACK(icvOnMouse), window ); g_signal_connect( window->frame, "delete-event", G_CALLBACK(icvOnClose), window ); #if defined(GTK_VERSION3) @@ -1076,7 +1078,7 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) G_CALLBACK(cvImageWidget_expose), window ); #endif //GTK_VERSION3 - gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ; + gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK) ; gtk_widget_show( window->frame ); gtk_window_set_title( GTK_WINDOW(window->frame), name ); @@ -1947,6 +1949,13 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da } state = event_button->state; } + else if( event->type == GDK_SCROLL ) + { + GdkEventButton* event_button = (GdkEventButton*)event; + + cv_event = CV_EVENT_MOUSEWHEEL; + state = event_button->state; + } if( cv_event >= 0 ){ // scale point if image is scaled @@ -1973,7 +1982,23 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da // if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) && // (unsigned)pt.y < (unsigned)(image_widget->original_image->height) ) { - int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) | + int flags = 0; + if (state & GDK_SCROLL_MASK) { + cv_event = CV_EVENT_MOUSEMOVE; + int orient = CV_EVENT_MOUSEWHEEL; + switch(event->scroll.direction) { + case GDK_SCROLL_RIGHT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_UP: flags |= ((1 << 16) | orient); + break; + case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_DOWN: flags |= ((-1 << 16) | orient); + break; + case GDK_SCROLL_SMOOTH: // to prevent make warning; TODO + ; + }; + }; + flags = flags | + (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) | (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) | (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) | (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) | From fd78e2cc6cdcbf7844dc38fb91d05922739f8bd9 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sat, 25 Jun 2016 00:47:22 +0300 Subject: [PATCH 033/153] highgui module: removed unused type_mouse_event mouse_wheel --- modules/highgui/src/window_QT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 7896b9f4d0..c0769dcc94 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -366,7 +366,7 @@ private slots: }; -enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3, mouse_wheel = 3 }; +enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3 }; static const int tableMouseButtons[][3]={ {CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP}, //mouse_up {CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN}, //mouse_down From a4e97120060bbe77aaa782e00d2e58dc308e151b Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Mon, 27 Jun 2016 13:34:41 +0300 Subject: [PATCH 034/153] Compilate switch-case with GTK_SCROLL_SMOOTH since GTK>=3.4 --- modules/highgui/src/window_gtk.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 928118e225..249d452e8d 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1993,8 +1993,10 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; case GDK_SCROLL_DOWN: flags |= ((-1 << 16) | orient); break; +#if (GTK_MAJOR_VERSION > 3 or (GTK_MAJOR_VERSION == 3 and GTK_MINOR_VERSION >= 4)) case GDK_SCROLL_SMOOTH: // to prevent make warning; TODO ; +#endif //GTK_MAJOR_VERSION > 3 or (GTK_MAJOR_VERSION == 3 and GTK_MINOR_VERSION >= 4) }; }; flags = flags | From 81c69ecd1644bd08dbeb73ce49d58486ee1b57d6 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Wed, 29 Jun 2016 23:01:57 +0300 Subject: [PATCH 035/153] highgui: window_gtk.cpp directive boolean operations or/and replaced by ||/&& to keep compatible with older systems --- modules/highgui/src/window_gtk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 249d452e8d..9e4798e889 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1993,10 +1993,10 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; case GDK_SCROLL_DOWN: flags |= ((-1 << 16) | orient); break; -#if (GTK_MAJOR_VERSION > 3 or (GTK_MAJOR_VERSION == 3 and GTK_MINOR_VERSION >= 4)) +#if (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4)) case GDK_SCROLL_SMOOTH: // to prevent make warning; TODO ; -#endif //GTK_MAJOR_VERSION > 3 or (GTK_MAJOR_VERSION == 3 and GTK_MINOR_VERSION >= 4) +#endif //GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4) }; }; flags = flags | From 2b08f29543c5115402d6d963e232493ce0d6d8ca Mon Sep 17 00:00:00 2001 From: Arthur Cinader Date: Thu, 30 Jun 2016 17:04:25 -0700 Subject: [PATCH 036/153] Allow for an optional mask for MatchTemplate_Demo --- .../MatchTemplate_Demo.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp index 0bf447d2f9..7cd07a5f03 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp @@ -13,7 +13,8 @@ using namespace std; using namespace cv; /// Global Variables -Mat img; Mat templ; Mat result; +bool use_mask; +Mat img; Mat templ; Mat mask; Mat result; const char* image_window = "Source Image"; const char* result_window = "Result window"; @@ -31,7 +32,7 @@ int main( int argc, char** argv ) if (argc < 3) { cout << "Not enough parameters" << endl; - cout << "Usage:\n./MatchTemplate_Demo " << endl; + cout << "Usage:\n./MatchTemplate_Demo []" << endl; return -1; } @@ -39,7 +40,12 @@ int main( int argc, char** argv ) img = imread( argv[1], IMREAD_COLOR ); templ = imread( argv[2], IMREAD_COLOR ); - if(img.empty() || templ.empty()) + if(argc > 3) { + use_mask = true; + mask = imread(argv[3], IMREAD_COLOR); + } + + if(img.empty() || templ.empty() || (use_mask && mask.empty())) { cout << "Can't read one of the images" << endl; return -1; @@ -76,7 +82,12 @@ void MatchingMethod( int, void* ) result.create( result_rows, result_cols, CV_32FC1 ); /// Do the Matching and Normalize - matchTemplate( img, templ, result, match_method ); + bool method_accepts_mask = CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED; + if (use_mask && method_accepts_mask) + { matchTemplate( img, templ, result, match_method, mask); } + else + { matchTemplate( img, templ, result, match_method); } + normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); /// Localizing the best match with minMaxLoc From 7dcac647e52ad16ebebca9584c01f2974643949a Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sun, 3 Jul 2016 13:31:25 +0300 Subject: [PATCH 037/153] highgui module: a bit readable onMouse flags mapping --- modules/highgui/src/window_gtk.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 9e4798e889..4949ed5467 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -61,6 +61,13 @@ #include #endif +#ifndef BIT_ALLIN + #define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) ) +#endif +#ifndef BIT_MAP + #define BIT_MAP(x,y,z) ( ((x)&(y)) ? (z) : 0 ) +#endif + // TODO Fix the initial window size when flags=0. Right now the initial window is by default // 320x240 size. A better default would be actual size of the image. Problem // is determining desired window size with trackbars while still allowing resizing. @@ -1006,6 +1013,7 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) CvWindow* window; int len; + int b_nautosize; cvInitSystem(1,(char**)&name); if( !name ) @@ -1087,11 +1095,11 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) hg_windows->prev = window; hg_windows = window; - gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 ); - + int b_nautosize = ((flags & CV_WINDOW_AUTOSIZE) == 0); + gtk_window_set_resizable( GTK_WINDOW(window->frame), b_nautosize ); // allow window to be resized - if( (flags & CV_WINDOW_AUTOSIZE)==0 ){ + if( b_nautosize ){ GdkGeometry geometry; geometry.min_width = 50; geometry.min_height = 50; @@ -1819,7 +1827,7 @@ static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer us { int code = 0; - if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S)) + if ( BIT_ALLIN(event->state, GDK_CONTROL_MASK) && (event->keyval == GDK_s || event->keyval == GDK_S)) { try { @@ -2000,12 +2008,13 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da }; }; flags = flags | - (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) | - (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) | - (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) | - (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) | - (state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) | - (state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0); + BIT_MAP(state, GDK_SHIFT_MASK, CV_EVENT_FLAG_SHIFTKEY) | + BIT_MAP(state, GDK_CONTROL_MASK, CV_EVENT_FLAG_CTRLKEY) | + BIT_MAP(state, GDK_MOD1_MASK, CV_EVENT_FLAG_ALTKEY) | + BIT_MAP(state, GDK_MOD2_MASK, CV_EVENT_FLAG_ALTKEY) | + BIT_MAP(state, GDK_BUTTON1_MASK, CV_EVENT_FLAG_LBUTTON) | + BIT_MAP(state, GDK_BUTTON2_MASK, CV_EVENT_FLAG_MBUTTON) | + BIT_MAP(state, GDK_BUTTON3_MASK, CV_EVENT_FLAG_RBUTTON); window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param ); } } From 1f2e15905443bdb0611283bdd2683bd56a648c19 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sun, 3 Jul 2016 15:52:59 +0300 Subject: [PATCH 038/153] highgui module: using event->scroll.delta_{x,y} instead parsing direction and added widget event mask GDK_SMOOTH_SCROLL_MASK for GTK>=3.4 --- modules/highgui/src/window_gtk.cpp | 71 ++++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 4949ed5467..bde5487035 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -52,8 +52,11 @@ #include #if (GTK_MAJOR_VERSION == 3) - #define GTK_VERSION3 + #define GTK_VERSION3 1 #endif //GTK_MAJOR_VERSION >= 3 +#if (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4)) + #define GTK_VERSION3_4 1 +#endif #ifdef HAVE_OPENGL #include @@ -1086,7 +1089,12 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) G_CALLBACK(cvImageWidget_expose), window ); #endif //GTK_VERSION3 + +#if defined(GTK_VERSION3_4) + gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK) ; +#else gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK) ; +#endif //GTK_VERSION3_4 gtk_widget_show( window->frame ); gtk_window_set_title( GTK_WINDOW(window->frame), name ); @@ -1095,7 +1103,7 @@ CV_IMPL int cvNamedWindow( const char* name, int flags ) hg_windows->prev = window; hg_windows = window; - int b_nautosize = ((flags & CV_WINDOW_AUTOSIZE) == 0); + b_nautosize = ((flags & CV_WINDOW_AUTOSIZE) == 0); gtk_window_set_resizable( GTK_WINDOW(window->frame), b_nautosize ); // allow window to be resized @@ -1911,7 +1919,7 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da CvWindow* window = (CvWindow*)user_data; CvPoint2D32f pt32f(-1., -1.); CvPoint pt(-1,-1); - int cv_event = -1, state = 0; + int cv_event = -1, state = 0, flags = 0; CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget ); if( window->signature != CV_WINDOW_MAGIC_VAL || @@ -1959,17 +1967,39 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da } else if( event->type == GDK_SCROLL ) { - GdkEventButton* event_button = (GdkEventButton*)event; +#if defined(GTK_VERSION3_4) + // NOTE: in current implementation doesn't possible to put into callback function delta_x and delta_y separetely + double delta = (event->scroll.delta_x + event->scroll.delta_y); + int orient = (event->scroll.delta_y!=0) ? CV_EVENT_MOUSEHWHEEL : CV_EVENT_MOUSEWHEEL; +#else + int orient = CV_EVENT_MOUSEWHEEL; +#endif //GTK_VERSION3_4 cv_event = CV_EVENT_MOUSEWHEEL; - state = event_button->state; + state = event->scroll.state; + + switch(event->scroll.direction) { +#if defined(GTK_VERSION3_4) + case GDK_SCROLL_SMOOTH: flags |= (((int)delta << 16) | orient); + break; +#endif //GTK_VERSION3_4 + case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_UP: flags |= ((-(int)1 << 16) | orient); + break; + case GDK_SCROLL_RIGHT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_DOWN: flags |= (((int)1 << 16) | orient); + break; + default: ; + }; } - if( cv_event >= 0 ){ + if( cv_event >= 0 ) + { // scale point if image is scaled if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 && image_widget->original_image && - image_widget->scaled_image ){ + image_widget->scaled_image ) + { // image origin is not necessarily at (0,0) #if defined (GTK_VERSION3) int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2; @@ -1983,32 +2013,15 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/ image_widget->scaled_image->rows ); } - else{ + else + { pt = cvPointFrom32f( pt32f ); } // if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) && // (unsigned)pt.y < (unsigned)(image_widget->original_image->height) ) { - int flags = 0; - if (state & GDK_SCROLL_MASK) { - cv_event = CV_EVENT_MOUSEMOVE; - int orient = CV_EVENT_MOUSEWHEEL; - switch(event->scroll.direction) { - case GDK_SCROLL_RIGHT: orient = CV_EVENT_MOUSEHWHEEL; - case GDK_SCROLL_UP: flags |= ((1 << 16) | orient); - break; - case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; - case GDK_SCROLL_DOWN: flags |= ((-1 << 16) | orient); - break; -#if (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4)) - case GDK_SCROLL_SMOOTH: // to prevent make warning; TODO - ; -#endif //GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4) - }; - }; - flags = flags | - BIT_MAP(state, GDK_SHIFT_MASK, CV_EVENT_FLAG_SHIFTKEY) | + flags |= BIT_MAP(state, GDK_SHIFT_MASK, CV_EVENT_FLAG_SHIFTKEY) | BIT_MAP(state, GDK_CONTROL_MASK, CV_EVENT_FLAG_CTRLKEY) | BIT_MAP(state, GDK_MOD1_MASK, CV_EVENT_FLAG_ALTKEY) | BIT_MAP(state, GDK_MOD2_MASK, CV_EVENT_FLAG_ALTKEY) | @@ -2019,8 +2032,8 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da } } - return FALSE; - } + return FALSE; +} static gboolean icvAlarm( gpointer user_data ) From 4e63bd04e570993ef3d0386a692d9bd6a6920130 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Mon, 4 Jul 2016 15:02:05 +0300 Subject: [PATCH 039/153] highgui module: mouse wheel - modification keys fixed, wheel event value is CV_EVENT_MOUSEWHEEL or CV_EVENT_MOUSEHWHEEL --- modules/highgui/src/window_gtk.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index bde5487035..475f85f9f6 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1975,22 +1975,22 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da int orient = CV_EVENT_MOUSEWHEEL; #endif //GTK_VERSION3_4 - cv_event = CV_EVENT_MOUSEWHEEL; state = event->scroll.state; switch(event->scroll.direction) { #if defined(GTK_VERSION3_4) - case GDK_SCROLL_SMOOTH: flags |= (((int)delta << 16) | orient); + case GDK_SCROLL_SMOOTH: flags |= (((int)delta << 16)); break; #endif //GTK_VERSION3_4 case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; - case GDK_SCROLL_UP: flags |= ((-(int)1 << 16) | orient); + case GDK_SCROLL_UP: flags |= ((-(int)1 << 16)); break; case GDK_SCROLL_RIGHT: orient = CV_EVENT_MOUSEHWHEEL; - case GDK_SCROLL_DOWN: flags |= (((int)1 << 16) | orient); + case GDK_SCROLL_DOWN: flags |= (((int)1 << 16)); break; default: ; }; + cv_event = orient; } if( cv_event >= 0 ) From 179998a8a2099e56ab8303f7e52ebfd11af71b1d Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Tue, 5 Jul 2016 12:02:16 +0300 Subject: [PATCH 040/153] highgui module: window_QT mouse wheel reuse variable delta instead call evnt->delta() --- modules/highgui/src/window_QT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 30f99d7708..70f3586210 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -2637,7 +2637,7 @@ void DefaultViewPort::wheelEvent(QWheelEvent* evnt) icvmouseHandler(evnt, mouse_wheel, cv_event, flags); icvmouseProcessing(QPoingF(pt), cv_event, flags); - scaleView(evnt->delta() / 240.0, pt); + scaleView(delta / 240.0, pt); viewport()->update(); QWidget::mouseWheel(evnt); From a6ade2b91418cfb2ea7c2e0b729243cb6ec3c8ac Mon Sep 17 00:00:00 2001 From: Arthur Cinader Date: Tue, 5 Jul 2016 12:58:47 -0400 Subject: [PATCH 041/153] Add the mask to the template matching demo documentation. --- .../images/Template_Matching_Mask_Example.jpg | Bin 0 -> 79095 bytes .../template_matching.markdown | 45 +++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 doc/tutorials/imgproc/histograms/template_matching/images/Template_Matching_Mask_Example.jpg diff --git a/doc/tutorials/imgproc/histograms/template_matching/images/Template_Matching_Mask_Example.jpg b/doc/tutorials/imgproc/histograms/template_matching/images/Template_Matching_Mask_Example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..711faec3b153f378e367e1a2ea252c41e5173356 GIT binary patch literal 79095 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 Date: Wed, 6 Jul 2016 19:53:32 +0300 Subject: [PATCH 042/153] cmake: python, allow dynamic symbols lookup from libpython.so --- cmake/OpenCVDetectPython.cmake | 8 ++-- modules/python/common.cmake | 54 +++++++++++++++++---------- modules/python/python2/CMakeLists.txt | 19 +--------- modules/python/python3/CMakeLists.txt | 19 +--------- modules/python/src2/gen2.py | 8 ++++ 5 files changed, 50 insertions(+), 58 deletions(-) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 64054d1efa..f304a50a42 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -75,10 +75,10 @@ if(NOT ${found}) if(NOT ANDROID AND NOT APPLE_FRAMEWORK) ocv_check_environment_variables(${library_env} ${include_dir_env}) - if(NOT ${${library_env}} EQUAL "") + if(NOT ${${library_env}} STREQUAL "") set(PYTHON_LIBRARY "${${library_env}}") endif() - if(NOT ${${include_dir_env}} EQUAL "") + if(NOT ${${include_dir_env}} STREQUAL "") set(PYTHON_INCLUDE_DIR "${${include_dir_env}}") endif() @@ -162,10 +162,10 @@ if(NOT ${found}) message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") message(STATUS "If you want to enable Python/Numpy support, set the following variables:") message(STATUS " PYTHON2_INCLUDE_PATH") - message(STATUS " PYTHON2_LIBRARIES") + message(STATUS " PYTHON2_LIBRARIES (optional on Unix-like systems)") message(STATUS " PYTHON2_NUMPY_INCLUDE_DIRS") message(STATUS " PYTHON3_INCLUDE_PATH") - message(STATUS " PYTHON3_LIBRARIES") + message(STATUS " PYTHON3_LIBRARIES (optional on Unix-like systems)") message(STATUS " PYTHON3_NUMPY_INCLUDE_DIRS") else() # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy diff --git a/modules/python/common.cmake b/modules/python/common.cmake index cf74f8dd95..c33f6a9101 100644 --- a/modules/python/common.cmake +++ b/modules/python/common.cmake @@ -1,11 +1,15 @@ # This file is included from a subdirectory set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../") +# try to use dynamic symbols linking with libpython.so +set(OPENCV_FORCE_PYTHON_LIBS OFF CACHE BOOL "") +string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + ocv_add_module(${MODULE_NAME} BINDINGS) ocv_module_include_directories( - "${PYTHON_INCLUDE_PATH}" - ${PYTHON_NUMPY_INCLUDE_DIRS} + "${${PYTHON}_INCLUDE_PATH}" + ${${PYTHON}_NUMPY_INCLUDE_DIRS} "${PYTHON_SOURCE_DIR}/src2" ) @@ -41,7 +45,7 @@ set(cv2_generated_hdrs file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") add_custom_command( OUTPUT ${cv2_generated_hdrs} - COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" + COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${PYTHON}" DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.py DEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.py DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt @@ -49,21 +53,28 @@ add_custom_command( ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs}) -if(PYTHON_DEBUG_LIBRARIES AND NOT PYTHON_LIBRARIES MATCHES "optimized.*debug") - ocv_target_link_libraries(${the_module} debug ${PYTHON_DEBUG_LIBRARIES} optimized ${PYTHON_LIBRARIES}) -else() - if(APPLE) - set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +if(APPLE) + set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS) + if(${PYTHON}_DEBUG_LIBRARIES AND NOT ${PYTHON}_LIBRARIES MATCHES "optimized.*debug") + ocv_target_link_libraries(${the_module} debug ${${PYTHON}_DEBUG_LIBRARIES} optimized ${${PYTHON}_LIBRARIES}) else() - ocv_target_link_libraries(${the_module} ${PYTHON_LIBRARIES}) + ocv_target_link_libraries(${the_module} ${${PYTHON}_LIBRARIES}) endif() endif() ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS}) -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))" - RESULT_VARIABLE PYTHON_CVPY_PROCESS - OUTPUT_VARIABLE CVPY_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) +if(DEFINED ${PYTHON}_CVPY_SUFFIX) + set(CVPY_SUFFIX "${${PYTHON}_CVPY_SUFFIX}") +else() + execute_process(COMMAND ${${PYTHON}_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))" + RESULT_VARIABLE PYTHON_CVPY_PROCESS + OUTPUT_VARIABLE CVPY_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT PYTHON_CVPY_PROCESS EQUAL 0) + set(CVPY_SUFFIX ".so") + endif() +endif() set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_INSTALL_SUBDIR}" @@ -95,7 +106,7 @@ if(MSVC AND NOT BUILD_SHARED_LIBS) set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() -if(MSVC AND NOT PYTHON_DEBUG_LIBRARIES) +if(MSVC AND NOT ${PYTHON}_DEBUG_LIBRARIES) set(PYTHON_INSTALL_CONFIGURATIONS CONFIGURATIONS Release) else() set(PYTHON_INSTALL_CONFIGURATIONS "") @@ -104,19 +115,22 @@ endif() if(WIN32) set(PYTHON_INSTALL_ARCHIVE "") else() - set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) + set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${${PYTHON}_PACKAGES_PATH} COMPONENT python) endif() -if(NOT INSTALL_CREATE_DISTRIB) +if(NOT INSTALL_CREATE_DISTRIB AND DEFINED ${PYTHON}_PACKAGES_PATH) + set(__dst "${${PYTHON}_PACKAGES_PATH}") install(TARGETS ${the_module} OPTIONAL ${PYTHON_INSTALL_CONFIGURATIONS} - RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python - LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python + RUNTIME DESTINATION "${__dst}" COMPONENT python + LIBRARY DESTINATION "${__dst}" COMPONENT python ${PYTHON_INSTALL_ARCHIVE} ) else() - if(DEFINED PYTHON_VERSION_MAJOR) - set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") + if(DEFINED ${PYTHON}_VERSION_MAJOR) + set(__ver "${${PYTHON}_VERSION_MAJOR}.${${PYTHON}_VERSION_MINOR}") + elseif(DEFINED ${PYTHON}_VERSION_STRING) + set(__ver "${${PYTHON}_VERSION_STRING}") else() set(__ver "unknown") endif() diff --git a/modules/python/python2/CMakeLists.txt b/modules/python/python2/CMakeLists.txt index 158763ec50..37e20fe330 100644 --- a/modules/python/python2/CMakeLists.txt +++ b/modules/python/python2/CMakeLists.txt @@ -1,4 +1,4 @@ -if(NOT PYTHON2LIBS_FOUND OR NOT PYTHON2_NUMPY_INCLUDE_DIRS) +if(NOT PYTHON2_INCLUDE_PATH OR NOT PYTHON2_NUMPY_INCLUDE_DIRS) ocv_module_disable(python2) endif() @@ -7,24 +7,9 @@ set(MODULE_NAME python2) # Buildbot requires Python 2 to be in root lib dir set(MODULE_INSTALL_SUBDIR "") -set(PYTHON_INCLUDE_PATH ${PYTHON2_INCLUDE_PATH}) -set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON2_NUMPY_INCLUDE_DIRS}) -set(PYTHON_EXECUTABLE ${PYTHON2_EXECUTABLE}) -set(PYTHON_DEBUG_LIBRARIES ${PYTHON2_DEBUG_LIBRARIES}) -set(PYTHON_LIBRARIES ${PYTHON2_LIBRARIES}) -set(PYTHON_PACKAGES_PATH ${PYTHON2_PACKAGES_PATH}) -set(PYTHON_VERSION_MAJOR ${PYTHON2_VERSION_MAJOR}) -set(PYTHON_VERSION_MINOR ${PYTHON2_VERSION_MINOR}) +set(PYTHON PYTHON2) include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) -unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_DIRS) -unset(PYTHON_EXECUTABLE) -unset(PYTHON_DEBUG_LIBRARIES) -unset(PYTHON_LIBRARIES) -unset(PYTHON_PACKAGES_PATH) -unset(PYTHON_VERSION_MAJOR) -unset(PYTHON_VERSION_MINOR) diff --git a/modules/python/python3/CMakeLists.txt b/modules/python/python3/CMakeLists.txt index 4b6fe4f141..da86ba5c5e 100644 --- a/modules/python/python3/CMakeLists.txt +++ b/modules/python/python3/CMakeLists.txt @@ -1,4 +1,4 @@ -if(NOT PYTHON3LIBS_FOUND OR NOT PYTHON3_NUMPY_INCLUDE_DIRS) +if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS) ocv_module_disable(python3) endif() @@ -6,24 +6,9 @@ set(the_description "The python3 bindings") set(MODULE_NAME python3) set(MODULE_INSTALL_SUBDIR python3) -set(PYTHON_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH}) -set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON3_NUMPY_INCLUDE_DIRS}) -set(PYTHON_EXECUTABLE ${PYTHON3_EXECUTABLE}) -set(PYTHON_DEBUG_LIBRARIES ${PYTHON3_DEBUG_LIBRARIES}) -set(PYTHON_LIBRARIES ${PYTHON3_LIBRARIES}) -set(PYTHON_PACKAGES_PATH ${PYTHON3_PACKAGES_PATH}) -set(PYTHON_VERSION_MAJOR ${PYTHON3_VERSION_MAJOR}) -set(PYTHON_VERSION_MINOR ${PYTHON3_VERSION_MINOR}) +set(PYTHON PYTHON3) include(../common.cmake) unset(MODULE_NAME) unset(MODULE_INSTALL_SUBDIR) -unset(PYTHON_INCLUDE_PATH) -unset(PYTHON_NUMPY_INCLUDE_DIRS) -unset(PYTHON_EXECUTABLE) -unset(PYTHON_DEBUG_LIBRARIES) -unset(PYTHON_LIBRARIES) -unset(PYTHON_PACKAGES_PATH) -unset(PYTHON_VERSION_MAJOR) -unset(PYTHON_VERSION_MINOR) diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 20c1007dee..0175f1e6db 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -44,6 +44,14 @@ gen_template_func_body = Template("""$code_decl """) py_major_version = sys.version_info[0] +if __name__ == "__main__": + if len(sys.argv) > 3: + if sys.argv[3] == 'PYTHON3': + py_major_version = 3 + elif sys.argv[3] == 'PYTHON2': + py_major_version = 2 + else: + raise Exception('Incorrect argument: expected PYTHON2 or PYTHON3, received: ' + sys.argv[3]) if py_major_version >= 3: head_init_str = "PyVarObject_HEAD_INIT(&PyType_Type, 0)" else: From 6f22f49c027be4802e56d17af669f0577a968986 Mon Sep 17 00:00:00 2001 From: look4pritam Date: Mon, 20 Apr 2015 17:57:57 +0530 Subject: [PATCH 043/153] Grassroots DiCoM i.e. GDCM based DICOM image reader is added. --- CMakeLists.txt | 8 + cmake/OpenCVFindLibsGrfmt.cmake | 12 ++ cmake/templates/cvconfig.h.in | 3 + modules/imgcodecs/CMakeLists.txt | 11 ++ modules/imgcodecs/src/gdcm_dicom.cpp | 216 +++++++++++++++++++++++++++ modules/imgcodecs/src/gdcm_dicom.hpp | 71 +++++++++ modules/imgcodecs/src/loadsave.cpp | 6 + 7 files changed, 327 insertions(+) create mode 100644 modules/imgcodecs/src/gdcm_dicom.cpp create mode 100644 modules/imgcodecs/src/gdcm_dicom.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ea42680b9..317edbb139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENNI2 "Include OpenNI2 support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_PNG "Include PNG support" ON) +OCV_OPTION(WITH_GDCM "Include DICOM support" OFF) OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_GIGEAPI "Include Smartek GigE support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_QT "Build with Qt Backend support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) @@ -1008,6 +1009,7 @@ if(WITH_PNG) else() status(" PNG:" "NO") endif() + if(WITH_TIFF) if(TIFF_VERSION_STRING AND TIFF_FOUND) status(" TIFF:" "${TIFF_LIBRARY} (ver ${TIFF_VERSION} - ${TIFF_VERSION_STRING})") @@ -1034,6 +1036,12 @@ else() status(" GDAL:" "NO") endif() +if(WITH_GDCM) + status(" GDCM:" GDCM_FOUND THEN "YES (ver ${GDCM_VERSION})" ELSE "NO") +else() + status(" GDCM:" "NO") +endif() + # ========================== VIDEO IO ========================== status("") status(" Video I/O:") diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index 614f844c7b..ced3c8ef7f 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -212,3 +212,15 @@ if(WITH_GDAL) ocv_include_directories(${GDAL_INCLUDE_DIR}) endif() endif() + +if (WITH_GDCM) + find_package(GDCM) + if(NOT GDCM_FOUND) + set(HAVE_GDCM NO) + ocv_clear_vars(GDCM_VERSION GDCM_LIBRARIES) + else() + set(HAVE_GDCM YES) + # include(${GDCM_USE_FILE}) + set(GDCM_LIBRARIES gdcmMSFF) # GDCM does not set this variable for some reason + endif() +endif() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index b86d44a6c1..2312742130 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -111,6 +111,9 @@ /* libpng/png.h needs to be included */ #cmakedefine HAVE_LIBPNG_PNG_H +/* GDCM DICOM codec */ +#cmakedefine HAVE_GDCM + /* V4L/V4L2 capturing support via libv4l */ #cmakedefine HAVE_LIBV4L diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 8b8c577166..1c7cc25b9e 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -35,6 +35,11 @@ if(HAVE_PNG) list(APPEND GRFMT_LIBS ${PNG_LIBRARIES}) endif() +if(HAVE_GDCM) + ocv_include_directories(${GDCM_INCLUDE_DIRS}) + list(APPEND GRFMT_LIBS ${GDCM_LIBRARIES}) +endif() + if(HAVE_TIFF) ocv_include_directories(${TIFF_INCLUDE_DIR}) list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES}) @@ -57,6 +62,12 @@ endif() file(GLOB grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.hpp) file(GLOB grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.cpp) + +if(HAVE_GDCM) + list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/gdcm_dicom.hpp) + list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/gdcm_dicom.cpp) +endif() + list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp) diff --git a/modules/imgcodecs/src/gdcm_dicom.cpp b/modules/imgcodecs/src/gdcm_dicom.cpp new file mode 100644 index 0000000000..58e38b95d0 --- /dev/null +++ b/modules/imgcodecs/src/gdcm_dicom.cpp @@ -0,0 +1,216 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" +#include "gdcm_dicom.hpp" + +#include + +namespace cv +{ + +/************************ DICOM decoder *****************************/ + +DICOMDecoder::DICOMDecoder() +{ + /// DICOM preable is 128 bytes (can have any vale, defaults to x00) + 4 bytes magic number (DICM) + m_signature = ""; + for(int iSize=0; iSize<128; iSize++) + { + m_signature = m_signature + "\xFF"; + } + + m_signature = m_signature + "\x44\x49\x43\x4D"; + + m_buf_supported = false; +} + + +DICOMDecoder::~DICOMDecoder() +{ +} + +bool DICOMDecoder::checkSignature( const String& signature ) const +{ + size_t len = signatureLength(); + bool bOK = signature.size() >= len; + for(int iIndex = 128; iIndex < len; iIndex++) + { + if(signature[iIndex] == m_signature[iIndex]) + { + continue; + } + else + { + bOK = false; + break; + } + } + + return(bOK); +} + +void DICOMDecoder::close() +{ +} + +ImageDecoder DICOMDecoder::newDecoder() const +{ + return makePtr(); +} + +bool DICOMDecoder::readHeader() +{ + gdcm::ImageReader csImageReader; + csImageReader.SetFileName(m_filename.c_str()); + if(!csImageReader.Read()) + { + return(false); + } + + bool bOK = true; + + const gdcm::Image &csImage = csImageReader.GetImage(); + if( ( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 ) + || ( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) + ) + { + gdcm::PixelFormat ePixelFormat = csImage.GetPixelFormat(); + if( ePixelFormat == gdcm::PixelFormat::INT8) + { + m_type = CV_8SC1; + } + else if( ePixelFormat == gdcm::PixelFormat::UINT8) + { + m_type = CV_8UC1; + } + else if( ePixelFormat == gdcm::PixelFormat::INT16) + { + m_type = CV_16SC1; + } + else if( ePixelFormat == gdcm::PixelFormat::UINT16) + { + m_type = CV_16UC1; + } + else if( ePixelFormat == gdcm::PixelFormat::INT32) + { + m_type = CV_32SC1; + } + else if( ePixelFormat == gdcm::PixelFormat::FLOAT32) + { + m_type = CV_32FC1; + } + else if( ePixelFormat == gdcm::PixelFormat::FLOAT64) + { + m_type = CV_64FC1; + } + else if( ePixelFormat == gdcm::PixelFormat::INT12) + { + bOK = false; + } + else if( ePixelFormat == gdcm::PixelFormat::UINT12) + { + bOK = false; + } + else if( ePixelFormat == gdcm::PixelFormat::UINT32) + { + bOK = false; + } + else if( ePixelFormat == gdcm::PixelFormat::SINGLEBIT) + { + bOK = false; + } + else + { + bOK = false; + } + } + else if( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) + { + gdcm::PixelFormat ePixelFormat = csImage.GetPixelFormat(); + if( ePixelFormat == gdcm::PixelFormat::UINT8) + { + m_type = CV_8UC3; + } + else + { + bOK = false; + } + } + else + { + bOK = false; + } + + if(bOK) + { + const unsigned int *piDimension = csImage.GetDimensions(); + m_width = piDimension[0]; + m_height = piDimension[1]; + if( ( m_width <=0 ) || ( m_height <=0 ) ) + { + bOK = false; + } + } + + return(bOK); +} + + +bool DICOMDecoder::readData( Mat& csImage ) +{ + csImage.create(m_width,m_height,m_type); + + gdcm::ImageReader csImageReader; + csImageReader.SetFileName(m_filename.c_str()); + if(!csImageReader.Read()) + { + return(false); + } + + bool bOK = true; + const gdcm::Image &csGDCMImage = csImageReader.GetImage(); + bOK = csGDCMImage.GetBuffer((char*)csImage.ptr()); + + return(bOK); +} +} diff --git a/modules/imgcodecs/src/gdcm_dicom.hpp b/modules/imgcodecs/src/gdcm_dicom.hpp new file mode 100644 index 0000000000..c9c5c23f27 --- /dev/null +++ b/modules/imgcodecs/src/gdcm_dicom.hpp @@ -0,0 +1,71 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef _GDCM_DICOM_H_ +#define _GDCM_DICOM_H_ + +#include "grfmt_base.hpp" + +namespace cv +{ + +// DICOM image reader using GDCM +class DICOMDecoder : public BaseImageDecoder +{ +public: + + DICOMDecoder(); + ~DICOMDecoder(); + + bool readData( Mat& img ); + bool readHeader(); + void close(); + + ImageDecoder newDecoder() const; + virtual bool checkSignature( const String& signature ) const; + +protected: +}; + +} + +#endif/*_GDCM_DICOM_H_*/ diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 70a31c37a2..c62b0bc722 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -45,6 +45,9 @@ #include "precomp.hpp" #include "grfmts.hpp" +#ifdef HAVE_GDCM +#include "gdcm_dicom.hpp" +#endif #undef min #undef max #include @@ -93,6 +96,9 @@ struct ImageCodecInitializer decoders.push_back( makePtr() ); encoders.push_back( makePtr() ); #endif + #ifdef HAVE_GDCM + decoders.push_back( makePtr() ); + #endif #ifdef HAVE_JASPER decoders.push_back( makePtr() ); encoders.push_back( makePtr() ); From 0fd0acf2e3697fd98ad89f214e3c6acc22bc55e3 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 7 Jul 2016 12:33:24 +0300 Subject: [PATCH 044/153] GDCM: modified compilation scheme - renamed source files - guard the contents - always include --- modules/imgcodecs/CMakeLists.txt | 5 ----- modules/imgcodecs/src/{gdcm_dicom.cpp => grfmt_gdcm.cpp} | 6 +++++- modules/imgcodecs/src/{gdcm_dicom.hpp => grfmt_gdcm.hpp} | 6 ++++++ modules/imgcodecs/src/grfmts.hpp | 1 + modules/imgcodecs/src/loadsave.cpp | 3 --- 5 files changed, 12 insertions(+), 9 deletions(-) rename modules/imgcodecs/src/{gdcm_dicom.cpp => grfmt_gdcm.cpp} (99%) rename modules/imgcodecs/src/{gdcm_dicom.hpp => grfmt_gdcm.hpp} (98%) diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 1c7cc25b9e..c614d79cdd 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -63,11 +63,6 @@ endif() file(GLOB grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.hpp) file(GLOB grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.cpp) -if(HAVE_GDCM) - list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/gdcm_dicom.hpp) - list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/gdcm_dicom.cpp) -endif() - list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp) diff --git a/modules/imgcodecs/src/gdcm_dicom.cpp b/modules/imgcodecs/src/grfmt_gdcm.cpp similarity index 99% rename from modules/imgcodecs/src/gdcm_dicom.cpp rename to modules/imgcodecs/src/grfmt_gdcm.cpp index 58e38b95d0..7aecf35f09 100644 --- a/modules/imgcodecs/src/gdcm_dicom.cpp +++ b/modules/imgcodecs/src/grfmt_gdcm.cpp @@ -41,7 +41,9 @@ //M*/ #include "precomp.hpp" -#include "gdcm_dicom.hpp" +#include "grfmt_gdcm.hpp" + +#ifdef HAVE_GDCM #include @@ -214,3 +216,5 @@ bool DICOMDecoder::readData( Mat& csImage ) return(bOK); } } + +#endif \ No newline at end of file diff --git a/modules/imgcodecs/src/gdcm_dicom.hpp b/modules/imgcodecs/src/grfmt_gdcm.hpp similarity index 98% rename from modules/imgcodecs/src/gdcm_dicom.hpp rename to modules/imgcodecs/src/grfmt_gdcm.hpp index c9c5c23f27..8a8e10032c 100644 --- a/modules/imgcodecs/src/gdcm_dicom.hpp +++ b/modules/imgcodecs/src/grfmt_gdcm.hpp @@ -43,6 +43,10 @@ #ifndef _GDCM_DICOM_H_ #define _GDCM_DICOM_H_ +#include "cvconfig.h" + +#ifdef HAVE_GDCM + #include "grfmt_base.hpp" namespace cv @@ -68,4 +72,6 @@ protected: } +#endif + #endif/*_GDCM_DICOM_H_*/ diff --git a/modules/imgcodecs/src/grfmts.hpp b/modules/imgcodecs/src/grfmts.hpp index c9e31530a8..7db1ac94a2 100644 --- a/modules/imgcodecs/src/grfmts.hpp +++ b/modules/imgcodecs/src/grfmts.hpp @@ -54,5 +54,6 @@ #include "grfmt_webp.hpp" #include "grfmt_hdr.hpp" #include "grfmt_gdal.hpp" +#include "grfmt_gdcm.hpp" #endif/*_GRFMTS_H_*/ diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index c62b0bc722..1c0b794b8e 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -45,9 +45,6 @@ #include "precomp.hpp" #include "grfmts.hpp" -#ifdef HAVE_GDCM -#include "gdcm_dicom.hpp" -#endif #undef min #undef max #include From f3bd508e6d96c3f988da2bb14a3a8ec7930193df Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 8 Jul 2016 16:08:11 +0300 Subject: [PATCH 045/153] GDCM: several improvements - fixed width and height order - removed unused methods - simplified signature matching - rewrote pixel format matching in more compact form - added dimensions number check (only 2 is allowed) - added target buffer size check - added debug messages in all failing points --- modules/imgcodecs/src/grfmt_gdcm.cpp | 181 ++++++++++++--------------- modules/imgcodecs/src/grfmt_gdcm.hpp | 9 +- 2 files changed, 80 insertions(+), 110 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_gdcm.cpp b/modules/imgcodecs/src/grfmt_gdcm.cpp index 7aecf35f09..a1d9e9d0af 100644 --- a/modules/imgcodecs/src/grfmt_gdcm.cpp +++ b/modules/imgcodecs/src/grfmt_gdcm.cpp @@ -45,8 +45,19 @@ #ifdef HAVE_GDCM +//#define DBG(...) printf(__VA_ARGS__) +#define DBG(...) + #include +static const size_t preamble_skip = 128; +static const size_t magic_len = 4; + +inline cv::String getMagic() +{ + return cv::String("\x44\x49\x43\x4D", 4); +} + namespace cv { @@ -54,45 +65,22 @@ namespace cv DICOMDecoder::DICOMDecoder() { - /// DICOM preable is 128 bytes (can have any vale, defaults to x00) + 4 bytes magic number (DICM) - m_signature = ""; - for(int iSize=0; iSize<128; iSize++) - { - m_signature = m_signature + "\xFF"; - } - - m_signature = m_signature + "\x44\x49\x43\x4D"; - + // DICOM preamble is 128 bytes (can have any value, defaults to 0) + 4 bytes magic number (DICM) + m_signature = String(preamble_skip, (char)'\x0') + getMagic(); m_buf_supported = false; } - -DICOMDecoder::~DICOMDecoder() -{ -} - bool DICOMDecoder::checkSignature( const String& signature ) const { - size_t len = signatureLength(); - bool bOK = signature.size() >= len; - for(int iIndex = 128; iIndex < len; iIndex++) + if (signature.size() >= preamble_skip + magic_len) { - if(signature[iIndex] == m_signature[iIndex]) + if (signature.substr(preamble_skip, magic_len) == getMagic()) { - continue; - } - else - { - bOK = false; - break; + return true; } } - - return(bOK); -} - -void DICOMDecoder::close() -{ + DBG("GDCM | Signature does not match\n"); + return false; } ImageDecoder DICOMDecoder::newDecoder() const @@ -106,90 +94,66 @@ bool DICOMDecoder::readHeader() csImageReader.SetFileName(m_filename.c_str()); if(!csImageReader.Read()) { + DBG("GDCM | Failed to open DICOM file\n"); return(false); } - bool bOK = true; - const gdcm::Image &csImage = csImageReader.GetImage(); - if( ( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 ) - || ( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) - ) + bool bOK = true; + switch (csImage.GetPhotometricInterpretation().GetType()) { - gdcm::PixelFormat ePixelFormat = csImage.GetPixelFormat(); - if( ePixelFormat == gdcm::PixelFormat::INT8) + case gdcm::PhotometricInterpretation::MONOCHROME1: + case gdcm::PhotometricInterpretation::MONOCHROME2: { - m_type = CV_8SC1; + switch (csImage.GetPixelFormat().GetScalarType()) + { + case gdcm::PixelFormat::INT8: m_type = CV_8SC1; break; + case gdcm::PixelFormat::UINT8: m_type = CV_8UC1; break; + case gdcm::PixelFormat::INT16: m_type = CV_16SC1; break; + case gdcm::PixelFormat::UINT16: m_type = CV_16UC1; break; + case gdcm::PixelFormat::INT32: m_type = CV_32SC1; break; + case gdcm::PixelFormat::FLOAT32: m_type = CV_32FC1; break; + case gdcm::PixelFormat::FLOAT64: m_type = CV_64FC1; break; + default: bOK = false; DBG("GDCM | Monochrome scalar type not supported\n"); break; + } + break; } - else if( ePixelFormat == gdcm::PixelFormat::UINT8) + + case gdcm::PhotometricInterpretation::RGB: { - m_type = CV_8UC1; + switch (csImage.GetPixelFormat().GetScalarType()) + { + case gdcm::PixelFormat::UINT8: m_type = CV_8UC3; break; + default: bOK = false; DBG("GDCM | RGB scalar type not supported\n"); break; + } + break; } - else if( ePixelFormat == gdcm::PixelFormat::INT16) - { - m_type = CV_16SC1; - } - else if( ePixelFormat == gdcm::PixelFormat::UINT16) - { - m_type = CV_16UC1; - } - else if( ePixelFormat == gdcm::PixelFormat::INT32) - { - m_type = CV_32SC1; - } - else if( ePixelFormat == gdcm::PixelFormat::FLOAT32) - { - m_type = CV_32FC1; - } - else if( ePixelFormat == gdcm::PixelFormat::FLOAT64) - { - m_type = CV_64FC1; - } - else if( ePixelFormat == gdcm::PixelFormat::INT12) + + default: { bOK = false; + DBG("GDCM | PI not supported: %s\n", csImage.GetPhotometricInterpretation().GetString()); + break; } - else if( ePixelFormat == gdcm::PixelFormat::UINT12) - { - bOK = false; - } - else if( ePixelFormat == gdcm::PixelFormat::UINT32) - { - bOK = false; - } - else if( ePixelFormat == gdcm::PixelFormat::SINGLEBIT) - { - bOK = false; - } - else - { - bOK = false; - } - } - else if( csImage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) - { - gdcm::PixelFormat ePixelFormat = csImage.GetPixelFormat(); - if( ePixelFormat == gdcm::PixelFormat::UINT8) - { - m_type = CV_8UC3; - } - else - { - bOK = false; - } - } - else - { - bOK = false; } if(bOK) + { + unsigned int ndim = csImage.GetNumberOfDimensions(); + if (ndim != 2) + { + DBG("GDCM | Invalid dimensions number: %d\n", ndim); + bOK = false; + } + } + if (bOK) { const unsigned int *piDimension = csImage.GetDimensions(); - m_width = piDimension[0]; - m_height = piDimension[1]; + m_height = piDimension[0]; + m_width = piDimension[1]; if( ( m_width <=0 ) || ( m_height <=0 ) ) { + DBG("GDCM | Invalid dimensions: %d x %d\n", piDimension[0], piDimension[1]); bOK = false; } } @@ -206,15 +170,28 @@ bool DICOMDecoder::readData( Mat& csImage ) csImageReader.SetFileName(m_filename.c_str()); if(!csImageReader.Read()) { - return(false); + DBG("GDCM | Failed to Read\n"); + return false; } - bool bOK = true; - const gdcm::Image &csGDCMImage = csImageReader.GetImage(); - bOK = csGDCMImage.GetBuffer((char*)csImage.ptr()); + const gdcm::Image &img = csImageReader.GetImage(); - return(bOK); -} + unsigned long len = img.GetBufferLength(); + if (len > csImage.elemSize() * csImage.total()) + { + DBG("GDCM | Buffer is bigger than Mat: %ld > %ld * %ld\n", len, csImage.elemSize(), csImage.total()); + return false; + } + + if (!img.GetBuffer((char*)csImage.ptr())) + { + DBG("GDCM | Failed to GetBuffer\n"); + return false; + } + DBG("GDCM | Read OK\n"); + return true; } -#endif \ No newline at end of file +} + +#endif // HAVE_GDCM \ No newline at end of file diff --git a/modules/imgcodecs/src/grfmt_gdcm.hpp b/modules/imgcodecs/src/grfmt_gdcm.hpp index 8a8e10032c..d8dc60f522 100644 --- a/modules/imgcodecs/src/grfmt_gdcm.hpp +++ b/modules/imgcodecs/src/grfmt_gdcm.hpp @@ -56,22 +56,15 @@ namespace cv class DICOMDecoder : public BaseImageDecoder { public: - DICOMDecoder(); - ~DICOMDecoder(); - bool readData( Mat& img ); bool readHeader(); - void close(); - ImageDecoder newDecoder() const; virtual bool checkSignature( const String& signature ) const; - -protected: }; } -#endif +#endif // HAVE_GDCM #endif/*_GDCM_DICOM_H_*/ From 59fabb2767f3efd59fc626573d83fdd4c7cd574c Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Thu, 23 Jun 2016 13:22:46 +0900 Subject: [PATCH 046/153] use NEON as same as SSE --- modules/objdetect/src/hog.cpp | 225 +++++++++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 2 deletions(-) diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 77dd71200f..1055525a82 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -222,6 +222,17 @@ void HOGDescriptor::copyTo(HOGDescriptor& c) const c.signedGradient = signedGradient; } +#if CV_NEON +// replace of _mm_set_ps +inline float32x4_t vsetq_f32(float f0, float f1, float f2, float f3) +{ + float32x4_t a = vdupq_n_f32(f0); + a = vsetq_lane_f32(f1, a, 1); + a = vsetq_lane_f32(f2, a, 2); + a = vsetq_lane_f32(f3, a, 3); + return a; +} +#endif void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, Size paddingTL, Size paddingBR) const { @@ -259,6 +270,21 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, _mm_storeu_ps(_data + i, _mm_cvtepi32_ps(idx)); idx = _mm_add_epi32(idx, ifour); } +#elif CV_NEON + const int indeces[] = { 0, 1, 2, 3 }; + uint32x4_t idx = *(uint32x4_t*)indeces; + uint32x4_t ifour = vdupq_n_u32(4); + + float* const _data = &_lut(0, 0); + if( gammaCorrection ) + for( i = 0; i < 256; i++ ) + _lut(0,i) = std::sqrt((float)i); + else + for( i = 0; i < 256; i += 4 ) + { + vst1q_f32(_data + i, vcvtq_f32_u32(idx)); + idx = vaddq_u32 (idx, ifour); + } #else if( gammaCorrection ) for( i = 0; i < 256; i++ ) @@ -299,6 +325,10 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, for ( ; x <= end - 4; x += 4) _mm_storeu_si128((__m128i*)(xmap + x), _mm_mullo_epi16(ithree, _mm_loadu_si128((const __m128i*)(xmap + x)))); +#elif CV_NEON + int32x4_t ithree = vdupq_n_s32(3); + for ( ; x <= end - 4; x += 4) + vst1q_s32(xmap + x, vmulq_s32(ithree, vld1q_s32(xmap + x))); #endif for ( ; x < end; ++x) xmap[x] *= 3; @@ -368,6 +398,45 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, _mm_storeu_ps(dbuf + x, _dx2); _mm_storeu_ps(dbuf + x + width, _dy2); } +#elif CV_NEON + for( ; x <= width - 4; x += 4 ) + { + int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3]; + typedef const uchar* const T; + T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1]; + T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x]; + T p22 = imgPtr + xmap[x+3], p20 = p02; + T p32 = imgPtr + xmap[x+4], p30 = p12; + + float32x4_t _dx0 = vsubq_f32(vsetq_f32(lut[p02[0]], lut[p12[0]], lut[p22[0]], lut[p32[0]]), + vsetq_f32(lut[p00[0]], lut[p10[0]], lut[p20[0]], lut[p30[0]])); + float32x4_t _dx1 = vsubq_f32(vsetq_f32(lut[p02[1]], lut[p12[1]], lut[p22[1]], lut[p32[1]]), + vsetq_f32(lut[p00[1]], lut[p10[1]], lut[p20[1]], lut[p30[1]])); + float32x4_t _dx2 = vsubq_f32(vsetq_f32(lut[p02[2]], lut[p12[2]], lut[p22[2]], lut[p32[2]]), + vsetq_f32(lut[p00[2]], lut[p10[2]], lut[p20[2]], lut[p30[2]])); + + float32x4_t _dy0 = vsubq_f32(vsetq_f32(lut[nextPtr[x0]], lut[nextPtr[x1]], lut[nextPtr[x2]], lut[nextPtr[x3]]), + vsetq_f32(lut[prevPtr[x0]], lut[prevPtr[x1]], lut[prevPtr[x2]], lut[prevPtr[x3]])); + float32x4_t _dy1 = vsubq_f32(vsetq_f32(lut[nextPtr[x0+1]], lut[nextPtr[x1+1]], lut[nextPtr[x2+1]], lut[nextPtr[x3+1]]), + vsetq_f32(lut[prevPtr[x0+1]], lut[prevPtr[x1+1]], lut[prevPtr[x2+1]], lut[prevPtr[x3+1]])); + float32x4_t _dy2 = vsubq_f32(vsetq_f32(lut[nextPtr[x0+2]], lut[nextPtr[x1+2]], lut[nextPtr[x2+2]], lut[nextPtr[x3+2]]), + vsetq_f32(lut[prevPtr[x0+2]], lut[prevPtr[x1+2]], lut[prevPtr[x2+2]], lut[prevPtr[x3+2]])); + + float32x4_t _mag0 = vaddq_f32(vmulq_f32(_dx0, _dx0), vmulq_f32(_dy0, _dy0)); + float32x4_t _mag1 = vaddq_f32(vmulq_f32(_dx1, _dx1), vmulq_f32(_dy1, _dy1)); + float32x4_t _mag2 = vaddq_f32(vmulq_f32(_dx2, _dx2), vmulq_f32(_dy2, _dy2)); + + uint32x4_t mask = vcgtq_f32(_mag2, _mag1); + _dx2 = vbslq_f32(mask, _dx2, _dx1); + _dy2 = vbslq_f32(mask, _dy2, _dy1); + + mask = vcgtq_f32(vmaxq_f32(_mag2, _mag1), _mag0); + _dx2 = vbslq_f32(mask, _dx2, _dx0); + _dy2 = vbslq_f32(mask, _dy2, _dy0); + + vst1q_f32(dbuf + x, _dx2); + vst1q_f32(dbuf + x + width, _dy2); + } #endif for( ; x < width; x++ ) { @@ -600,6 +669,19 @@ void HOGCache::init(const HOGDescriptor* _descriptor, idx = _mm_add_epi32(idx, ifour); _mm_storeu_ps(_di + i, t); } + #elif CV_NEON + const int a[] = { 0, 1, 2, 3 }; + int32x4_t idx = vld1q_s32(a); + float32x4_t _bw = vdupq_n_f32(bw), _bh = vdupq_n_f32(bh); + int32x4_t ifour = vdupq_n_s32(4); + + for (; i <= blockSize.height - 4; i += 4) + { + float32x4_t t = vsubq_f32(vcvtq_f32_s32(idx), _bh); + t = vmulq_f32(t, t); + idx = vaddq_s32(idx, ifour); + vst1q_f32(_di + i, t); + } #endif for ( ; i < blockSize.height; ++i) { @@ -617,6 +699,15 @@ void HOGCache::init(const HOGDescriptor* _descriptor, idx = _mm_add_epi32(idx, ifour); _mm_storeu_ps(_dj + j, t); } + #elif CV_NEON + idx = vld1q_s32(a); + for (; j <= blockSize.width - 4; j += 4) + { + float32x4_t t = vsubq_f32(vcvtq_f32_s32(idx), _bw); + t = vmulq_f32(t, t); + idx = vaddq_s32(idx, ifour); + vst1q_f32(_dj + j, t); + } #endif for ( ; j < blockSize.width; ++j) { @@ -839,6 +930,31 @@ const float* HOGCache::getBlock(Point pt, float* buf) t1 = hist[h1] + hist1[1]; hist[h0] = t0; hist[h1] = t1; } +#elif CV_NEON + float hist0[4], hist1[4]; + for( ; k < C2; k++ ) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + const uchar* const h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; + + float32x4_t _a0 = vdupq_n_f32(a[0]), _a1 = vdupq_n_f32(a[1]); + float32x4_t _w = vmulq_f32(vdupq_n_f32(pk.gradWeight), vld1q_f32(pk.histWeights)); + + float32x4_t _h0 = vsetq_f32((blockHist + pk.histOfs[0])[h0], (blockHist + pk.histOfs[1])[h0], 0, 0); + float32x4_t _h1 = vsetq_f32((blockHist + pk.histOfs[0])[h1], (blockHist + pk.histOfs[1])[h1], 0, 0); + + float32x4_t _t0 = vmlaq_f32(_h0, _a0, _w), _t1 = vmlaq_f32(_h1, _a1, _w); + vst1q_f32(hist0, _t0); + vst1q_f32(hist1, _t1); + + (blockHist + pk.histOfs[0])[h0] = hist0[0]; + (blockHist + pk.histOfs[1])[h0] = hist0[1]; + + (blockHist + pk.histOfs[0])[h1] = hist1[0]; + (blockHist + pk.histOfs[1])[h1] = hist1[1]; + } #else for( ; k < C2; k++ ) { @@ -918,6 +1034,41 @@ const float* HOGCache::getBlock(Point pt, float* buf) // (pk.histOfs[2] + blockHist)[h1] = hist1[2]; // (pk.histOfs[3] + blockHist)[h1] = hist1[3]; } +#elif CV_NEON + for( ; k < C4; k++ ) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + const uchar* const h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; + + float32x4_t _a0 = vdupq_n_f32(a[0]), _a1 = vdupq_n_f32(a[1]); + float32x4_t _w = vmulq_f32(vdupq_n_f32(pk.gradWeight), vld1q_f32(pk.histWeights)); + + float32x4_t _h0 = vsetq_f32((blockHist + pk.histOfs[0])[h0], + (blockHist + pk.histOfs[1])[h0], + (blockHist + pk.histOfs[2])[h0], + (blockHist + pk.histOfs[3])[h0]); + float32x4_t _h1 = vsetq_f32((blockHist + pk.histOfs[0])[h1], + (blockHist + pk.histOfs[1])[h1], + (blockHist + pk.histOfs[2])[h1], + (blockHist + pk.histOfs[3])[h1]); + + + float32x4_t _t0 = vmlaq_f32(_h0, _a0, _w), _t1 = vmlaq_f32(_h1, _a1, _w); + vst1q_f32(hist0, _t0); + vst1q_f32(hist1, _t1); + + (blockHist + pk.histOfs[0])[h0] = hist0[0]; + (blockHist + pk.histOfs[1])[h0] = hist0[1]; + (blockHist + pk.histOfs[2])[h0] = hist0[2]; + (blockHist + pk.histOfs[3])[h0] = hist0[3]; + + (blockHist + pk.histOfs[0])[h1] = hist1[0]; + (blockHist + pk.histOfs[1])[h1] = hist1[1]; + (blockHist + pk.histOfs[2])[h1] = hist1[2]; + (blockHist + pk.histOfs[3])[h1] = hist1[3]; + } #else for( ; k < C4; k++ ) { @@ -973,6 +1124,16 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const s = _mm_add_ps(s, _mm_mul_ps(p0, p0)); } _mm_storeu_ps(partSum, s); +#elif CV_NEON + float32x4_t p0 = vld1q_f32(hist); + float32x4_t s = vmulq_f32(p0, p0); + + for (i = 4; i <= sz - 4; i += 4) + { + p0 = vld1q_f32(hist + i); + s = vaddq_f32(s, vmulq_f32(p0, p0)); + } + vst1q_f32(partSum, s); #else partSum[0] = 0.0f; partSum[1] = 0.0f; @@ -1014,6 +1175,25 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const } _mm_storeu_ps(partSum, s); +#elif CV_NEON + float32x4_t _scale = vdupq_n_f32(scale); + static float32x4_t _threshold = vdupq_n_f32(thresh); + + float32x4_t p = vmulq_f32(_scale, vld1q_f32(hist)); + p = vminq_f32(p, _threshold); + s = vmulq_f32(p, p); + vst1q_f32(hist, p); + + for(i = 4 ; i <= sz - 4; i += 4) + { + p = vld1q_f32(hist + i); + p = vmulq_f32(p, _scale); + p = vminq_f32(p, _threshold); + s = vaddq_f32(s, vmulq_f32(p, p)); + vst1q_f32(hist + i, p); + } + + vst1q_f32(partSum, s); #else partSum[0] = 0.0f; partSum[1] = 0.0f; @@ -1048,6 +1228,13 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const __m128 t = _mm_mul_ps(_scale2, _mm_loadu_ps(hist + i)); _mm_storeu_ps(hist + i, t); } +#elif CV_NEON + float32x4_t _scale2 = vdupq_n_f32(scale); + for ( ; i <= sz - 4; i += 4) + { + float32x4_t t = vmulq_f32(_scale2, vld1q_f32(hist + i)); + vst1q_f32(hist + i, t); + } #endif for ( ; i < sz; ++i) hist[i] *= scale; @@ -1489,7 +1676,7 @@ void HOGDescriptor::detect(const Mat& img, double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; std::vector blockHist(blockHistogramSize); -#if CV_SSE2 +#if CV_SSE2 || CV_NEON float partSum[4]; #endif @@ -1535,6 +1722,23 @@ void HOGDescriptor::detect(const Mat& img, double t0 = partSum[0] + partSum[1]; double t1 = partSum[2] + partSum[3]; s += t0 + t1; +#elif CV_NEON + float32x4_t _vec = vld1q_f32(vec); + float32x4_t _svmVec = vld1q_f32(svmVec); + float32x4_t sum = vmulq_f32(_svmVec, _vec); + + for( k = 4; k <= blockHistogramSize - 4; k += 4 ) + { + _vec = vld1q_f32(vec + k); + _svmVec = vld1q_f32(svmVec + k); + + sum = vaddq_f32(sum, vmulq_f32(_vec, _svmVec)); + } + + vst1q_f32(partSum, sum); + double t0 = partSum[0] + partSum[1]; + double t1 = partSum[2] + partSum[3]; + s += t0 + t1; #else for( k = 0; k <= blockHistogramSize - 4; k += 4 ) s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + @@ -3357,7 +3561,7 @@ void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector & double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; std::vector blockHist(blockHistogramSize); -#if CV_SSE2 +#if CV_SSE2 || CV_NEON float partSum[4]; #endif @@ -3401,6 +3605,23 @@ void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector & double t0 = partSum[0] + partSum[1]; double t1 = partSum[2] + partSum[3]; s += t0 + t1; +#elif CV_NEON + float32x4_t _vec = vld1q_f32(vec); + float32x4_t _svmVec = vld1q_f32(svmVec); + float32x4_t sum = vmulq_f32(_svmVec, _vec); + + for( k = 4; k <= blockHistogramSize - 4; k += 4 ) + { + _vec = vld1q_f32(vec + k); + _svmVec = vld1q_f32(svmVec + k); + + sum = vaddq_f32(sum, vmulq_f32(_vec, _svmVec)); + } + + vst1q_f32(partSum, sum); + double t0 = partSum[0] + partSum[1]; + double t1 = partSum[2] + partSum[3]; + s += t0 + t1; #else for( k = 0; k <= blockHistogramSize - 4; k += 4 ) s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + From 0ed250cb5d8ffa68a78526d50c6fc90ba2999999 Mon Sep 17 00:00:00 2001 From: Arthur Cinader Date: Mon, 11 Jul 2016 11:35:50 -0400 Subject: [PATCH 047/153] Implement PR feedback: 1. Explain grayscale input still read as three channel 2. Fix typo 3. Add more details to image match explanation to include the use of masks --- .../template_matching.markdown | 23 ++++++++++++------- .../MatchTemplate_Demo.cpp | 4 ++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown index 5196f424a8..bdba55a799 100644 --- a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown +++ b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown @@ -20,7 +20,7 @@ Template matching is a technique for finding areas of an image that match (are s template image (patch). While the patch must be a rectangle it may be that not all of the -rectangle is relevent. In such a case, a mask can be used to isolate the portion of the patch +rectangle is relevant. In such a case, a mask can be used to isolate the portion of the patch that should be used to find the match. ### How does it work? @@ -60,7 +60,7 @@ that should be used to find the match. -# **Source image (I):** The image in which we expect to find a match to the template image -# **Template image (T):** The patch image which will be compared to the template image - -# **Mask image (M):** The mask, a greyscale image that masks the template + -# **Mask image (M):** The mask, a grayscale image that masks the template - Only two matching methods currently accept a mask: CV_TM_SQDIFF and CV_TM_CCORR_NORMED (see @@ -70,10 +70,13 @@ that should be used to find the match. - The mask must have the same dimensions as the template -- The mask should be a greyscale image where each pixel contains some value from black to white. +- The mask should be a grayscale image where each pixel contains some value from black to white. Pixels that are white are fully included in calculating the best match. Pixels that are black are excluded from the match. A value between black and white will include some of - the match proportion to how dark the pixel is. + the match in proportion to how dark the pixel is. Although the image should be a grayscale whose + output from the file command should look something like: "PNG image data, 128 x 128, 8-bit gray + +alpha, non-interlaced", opencv will read the image into an rgb matrix that will be applied + during the image match. ![](images/Template_Matching_Mask_Example.jpg) @@ -140,10 +143,14 @@ Explanation int match_method; int max_Trackbar = 5; @endcode --# Load the source image and template: +-# Load the source image, template, and optionally, if supported for the matching method, a mask: @code{.cpp} - img = imread( argv[1], IMREAD_COLOR ); - templ = imread( argv[2], IMREAD_COLOR ); + bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); + if (use_mask && method_accepts_mask) + { matchTemplate( img, templ, result, match_method, mask); } + else + { matchTemplate( img, templ, result, match_method); } + @endcode -# Create the windows to show the results: @code{.cpp} @@ -177,7 +184,7 @@ Explanation @endcode -# Perform the template matching operation: @code{.cpp} - bool method_accepts_mask = CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED; + bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); if (use_mask && method_accepts_mask) { matchTemplate( img, templ, result, match_method, mask); } else diff --git a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp index 7cd07a5f03..1042e2cff2 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp @@ -42,7 +42,7 @@ int main( int argc, char** argv ) if(argc > 3) { use_mask = true; - mask = imread(argv[3], IMREAD_COLOR); + mask = imread( argv[3], IMREAD_COLOR ); } if(img.empty() || templ.empty() || (use_mask && mask.empty())) @@ -82,7 +82,7 @@ void MatchingMethod( int, void* ) result.create( result_rows, result_cols, CV_32FC1 ); /// Do the Matching and Normalize - bool method_accepts_mask = CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED; + bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED); if (use_mask && method_accepts_mask) { matchTemplate( img, templ, result, match_method, mask); } else From ddc0b42bc389ae17733fed3189acedb6791953dc Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 14 Jun 2016 16:01:36 +0300 Subject: [PATCH 048/153] migration: github.com/opencv/opencv --- .github/ISSUE_TEMPLATE.md | 2 +- 3rdparty/ffmpeg/ffmpeg.cmake | 2 +- 3rdparty/ippicv/downloader.cmake | 2 +- CONTRIBUTING.md | 2 +- README.md | 4 ++-- doc/Doxyfile.in | 2 +- .../py_feature2d/py_brief/py_brief.markdown | 2 +- .../py_sift_intro/py_sift_intro.markdown | 2 +- .../py_setup/py_intro/py_intro.markdown | 2 +- .../py_setup_in_fedora/py_setup_in_fedora.markdown | 2 +- .../py_setup_in_windows.markdown | 2 +- .../camera_calibration/camera_calibration.markdown | 6 +++--- .../interactive_calibration.markdown | 2 +- .../basic_geometric_drawing.markdown | 2 +- .../discrete_fourier_transform.markdown | 4 ++-- .../file_input_output_with_xml_yml.markdown | 2 +- .../how_to_scan_images/how_to_scan_images.markdown | 2 +- .../how_to_use_ippa_conversion.markdown | 2 +- .../interoperability_with_OpenCV_1.markdown | 4 ++-- .../mat_mask_operations.markdown | 2 +- .../mat_the_basic_image_container.markdown | 2 +- .../corner_subpixeles/corner_subpixeles.markdown | 2 +- .../generic_corner_detector.markdown | 2 +- .../good_features_to_track.markdown | 2 +- .../harris_detector/harris_detector.markdown | 2 +- .../gpu_basics_similarity.markdown | 2 +- .../erosion_dilatation/erosion_dilatation.markdown | 2 +- .../gausian_median_blur_bilateral_filter.markdown | 2 +- .../back_projection/back_projection.markdown | 6 +++--- .../histogram_calculation.markdown | 2 +- .../histogram_comparison.markdown | 2 +- .../histogram_equalization.markdown | 2 +- .../template_matching/template_matching.markdown | 2 +- .../canny_detector/canny_detector.markdown | 2 +- .../copyMakeBorder/copyMakeBorder.markdown | 2 +- .../distance_transform.markdown | 2 +- .../imgproc/imgtrans/filter_2d/filter_2d.markdown | 2 +- .../imgtrans/hough_circle/hough_circle.markdown | 4 ++-- .../imgtrans/hough_lines/hough_lines.markdown | 4 ++-- .../laplace_operator/laplace_operator.markdown | 2 +- .../imgproc/imgtrans/remap/remap.markdown | 2 +- .../sobel_derivatives/sobel_derivatives.markdown | 2 +- .../imgtrans/warp_affine/warp_affine.markdown | 2 +- .../morph_lines_detection/moprh_lines_detection.md | 2 +- .../opening_closing_hats.markdown | 2 +- doc/tutorials/imgproc/pyramids/pyramids.markdown | 2 +- .../bounding_rects_circles.markdown | 2 +- .../bounding_rotated_ellipses.markdown | 2 +- .../find_contours/find_contours.markdown | 2 +- .../imgproc/shapedescriptors/hull/hull.markdown | 2 +- .../shapedescriptors/moments/moments.markdown | 2 +- .../point_polygon_test/point_polygon_test.markdown | 2 +- doc/tutorials/imgproc/threshold/threshold.markdown | 2 +- .../threshold_inRange/threshold_inRange.markdown | 2 +- .../android_ocl_intro.markdown | 4 ++-- .../clojure_dev_intro/clojure_dev_intro.markdown | 2 +- .../arm_crosscompile_with_cmake.markdown | 6 +++--- .../desktop_java/java_dev_intro.markdown | 4 ++-- .../display_image/display_image.markdown | 2 +- .../introduction/ios_install/ios_install.markdown | 4 ++-- .../linux_install/linux_install.markdown | 14 +++++++------- .../transition_guide/transition_guide.markdown | 2 +- .../windows_install/windows_install.markdown | 4 ++-- .../windows_visual_studio_Opencv.markdown | 4 ++-- .../introduction_to_pca.markdown | 4 ++-- .../ml/non_linear_svms/non_linear_svms.markdown | 2 +- .../cascade_classifier/cascade_classifier.markdown | 4 ++-- .../background_subtraction.markdown | 2 +- doc/tutorials/videoio/intelperc.markdown | 2 +- doc/tutorials/videoio/kinect_openni.markdown | 2 +- .../video_input_psnr_ssim.markdown | 4 ++-- .../videoio/video-write/video_write.markdown | 2 +- .../viz/creating_widgets/creating_widgets.markdown | 2 +- .../viz/launching_viz/launching_viz.markdown | 2 +- .../viz/transformations/transformations.markdown | 2 +- doc/tutorials/viz/widget_pose/widget_pose.markdown | 2 +- modules/core/doc/cuda.markdown | 2 +- modules/highgui/include/opencv2/highgui.hpp | 2 +- modules/objdetect/include/opencv2/objdetect.hpp | 2 +- modules/python/test/test_digits.py | 2 +- modules/python/test/test_gaussian_mix.py | 2 +- modules/python/test/tests_common.py | 2 +- modules/videoio/include/opencv2/videoio.hpp | 2 +- modules/videoio/src/cap_libv4l.cpp | 2 +- modules/videoio/src/cap_v4l.cpp | 2 +- platforms/winrt/readme.txt | 2 +- .../CameraCalibrationActivity.java | 2 +- samples/cpp/facial_features.cpp | 4 ++-- samples/cpp/stereo_calib.cpp | 2 +- samples/python/digits.py | 2 +- samples/python/digits_video.py | 2 +- samples/python/find_obj.py | 2 +- samples/python/gaussian_mix.py | 2 +- samples/python/video_v4l2.py | 2 +- 94 files changed, 120 insertions(+), 120 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4f1453a2ff..e72c70d8c3 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ diff --git a/3rdparty/ffmpeg/ffmpeg.cmake b/3rdparty/ffmpeg/ffmpeg.cmake index 448ad2bb2c..c227f10bee 100644 --- a/3rdparty/ffmpeg/ffmpeg.cmake +++ b/3rdparty/ffmpeg/ffmpeg.cmake @@ -5,7 +5,7 @@ set(FFMPEG_FILE_HASH_BIN32 "89c783eee1c47bfc733f08334ec2e31c") set(FFMPEG_FILE_HASH_BIN64 "35fe6ccdda6d7a04e9056b0d73b98e76") set(FFMPEG_FILE_HASH_CMAKE "8606f947a780071f8fcce8cbf39ceef5") -set(FFMPEG_DOWNLOAD_URL ${OPENCV_FFMPEG_URL};$ENV{OPENCV_FFMPEG_URL};https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${FFMPEG_BINARIES_COMMIT}/ffmpeg/) +set(FFMPEG_DOWNLOAD_URL ${OPENCV_FFMPEG_URL};$ENV{OPENCV_FFMPEG_URL};https://raw.githubusercontent.com/opencv/opencv_3rdparty/${FFMPEG_BINARIES_COMMIT}/ffmpeg/) ocv_download(PACKAGE opencv_ffmpeg.dll HASH ${FFMPEG_FILE_HASH_BIN32} diff --git a/3rdparty/ippicv/downloader.cmake b/3rdparty/ippicv/downloader.cmake index a6016dbe10..e20804d7b4 100644 --- a/3rdparty/ippicv/downloader.cmake +++ b/3rdparty/ippicv/downloader.cmake @@ -64,7 +64,7 @@ function(_icv_downloader) if(DEFINED ENV{OPENCV_ICV_URL}) set(OPENCV_ICV_URL $ENV{OPENCV_ICV_URL}) else() - set(OPENCV_ICV_URL "https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${IPPICV_BINARIES_COMMIT}/ippicv") + set(OPENCV_ICV_URL "https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_BINARIES_COMMIT}/ippicv") endif() endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1e13c89969..318e9ac8fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ ## Contributing guidelines -All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/Itseez/opencv/wiki/How_to_contribute). +All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/opencv/opencv/wiki/How_to_contribute). diff --git a/README.md b/README.md index 7dbc823200..37543b6e5d 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ * Homepage: * Docs: * Q&A forum: -* Issue tracking: +* Issue tracking: #### Contributing -Please read before starting work on a pull request: +Please read before starting work on a pull request: Summary of guidelines: diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index c4da726035..45c085cc34 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -150,7 +150,7 @@ BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = @CMAKE_DOXYGEN_GENERATE_QHP@ QCH_FILE = ../opencv-@OPENCV_VERSION@.qch -QHP_NAMESPACE = org.itseez.opencv.@OPENCV_VERSION@ +QHP_NAMESPACE = org.opencv.@OPENCV_VERSION@ QHP_VIRTUAL_FOLDER = opencv QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = diff --git a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown index e2c0ed428e..33cbfebf49 100644 --- a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown +++ b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown @@ -49,7 +49,7 @@ BRIEF in OpenCV Below code shows the computation of BRIEF descriptors with the help of CenSurE detector. (CenSurE detector is called STAR detector in OpenCV) -note, that you need [opencv contrib](https://github.com/Itseez/opencv_contrib)) to use this. +note, that you need [opencv contrib](https://github.com/opencv/opencv_contrib)) to use this. @code{.py} import numpy as np import cv2 diff --git a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown index b12505adc9..da4b878db0 100644 --- a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown @@ -104,7 +104,7 @@ greater than 0.8, they are rejected. It eliminaters around 90% of false matches So this is a summary of SIFT algorithm. For more details and understanding, reading the original paper is highly recommended. Remember one thing, this algorithm is patented. So this algorithm is -included in [the opencv contrib repo](https://github.com/Itseez/opencv_contrib) +included in [the opencv contrib repo](https://github.com/opencv/opencv_contrib) SIFT in OpenCV -------------- diff --git a/doc/py_tutorials/py_setup/py_intro/py_intro.markdown b/doc/py_tutorials/py_setup/py_intro/py_intro.markdown index 007a71ce72..c8041bb2c5 100644 --- a/doc/py_tutorials/py_setup/py_intro/py_intro.markdown +++ b/doc/py_tutorials/py_setup/py_intro/py_intro.markdown @@ -58,7 +58,7 @@ OpenCV Needs You !!! Since OpenCV is an open source initiative, all are welcome to make contributions to the library, documentation, and tutorials. If you find any mistake in this tutorial (from a small spelling mistake to an egregious error in code or concept), feel free to correct it by cloning OpenCV in -[GitHub](https://github.com/Itseez/opencv) and submitting a pull request. OpenCV developers will +[GitHub](https://github.com/opencv/opencv) and submitting a pull request. OpenCV developers will check your pull request, give you important feedback and (once it passes the approval of the reviewer) it will be merged into OpenCV. You will then become an open source contributor :-) diff --git a/doc/py_tutorials/py_setup/py_setup_in_fedora/py_setup_in_fedora.markdown b/doc/py_tutorials/py_setup/py_setup_in_fedora/py_setup_in_fedora.markdown index b8f57e72a6..da65dd4772 100644 --- a/doc/py_tutorials/py_setup/py_setup_in_fedora/py_setup_in_fedora.markdown +++ b/doc/py_tutorials/py_setup/py_setup_in_fedora/py_setup_in_fedora.markdown @@ -119,7 +119,7 @@ Or you can download latest source from OpenCV's github repo. (If you want to con choose this. It always keeps your OpenCV up-to-date). For that, you need to install **Git** first. @code{.sh} yum install git -git clone https://github.com/Itseez/opencv.git +git clone https://github.com/opencv/opencv.git @endcode It will create a folder OpenCV in home directory (or the directory you specify). The cloning may take some time depending upon your internet connection. diff --git a/doc/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.markdown b/doc/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.markdown index 807e5467bd..3ff4e82e8c 100644 --- a/doc/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.markdown +++ b/doc/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.markdown @@ -76,7 +76,7 @@ Building OpenCV from source -# Download OpenCV source. It can be from [Sourceforge](http://sourceforge.net/projects/opencvlibrary/) (for official release version) or - from [Github](https://github.com/Itseez/opencv) (for latest source). + from [Github](https://github.com/opencv/opencv) (for latest source). -# Extract it to a folder, opencv and create a new folder build in it. -# Open CMake-gui (*Start \> All Programs \> CMake-gui*) -# Fill the fields as follows (see the image below): diff --git a/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown b/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown index 1a7b906872..2c6973141e 100644 --- a/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown +++ b/doc/tutorials/calib3d/camera_calibration/camera_calibration.markdown @@ -77,13 +77,13 @@ Source code You may also find the source code in the `samples/cpp/tutorial_code/calib3d/camera_calibration/` folder of the OpenCV source library or [download it from here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp). The program has a +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp). The program has a single argument: the name of its configuration file. If none is given then it will try to open the one named "default.xml". [Here's a sample configuration file -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml) in XML format. In the +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml) in XML format. In the configuration file you may choose to use camera as an input, a video file or an image list. If you opt for the last one, you will need to create a configuration file where you enumerate the images to -use. Here's [an example of this ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/VID5.xml). +use. Here's [an example of this ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration/VID5.xml). The important part to remember is that the images need to be specified using the absolute path or the relative one from your application's working directory. You may find all this in the samples directory mentioned above. diff --git a/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown b/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown index 123b63689d..0c4d67ec85 100644 --- a/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown +++ b/doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown @@ -92,7 +92,7 @@ QR faster than SVD, but potentially less precise - *camera_resolution*: resolution of camera which is used for calibration **Note:** *charuco_dict*, *charuco_square_lenght* and *charuco_marker_size* are used for chAruco pattern generation -(see Aruco module description for details: [Aruco tutorials](https://github.com/Itseez/opencv_contrib/tree/master/modules/aruco/tutorials)) +(see Aruco module description for details: [Aruco tutorials](https://github.com/opencv/opencv_contrib/tree/master/modules/aruco/tutorials)) Default chAruco pattern: diff --git a/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown b/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown index 61134bd487..4c68517bbc 100644 --- a/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown +++ b/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown @@ -47,7 +47,7 @@ Code ---- - This code is in your OpenCV sample folder. Otherwise you can grab it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp) Explanation ----------- diff --git a/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.markdown b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.markdown index 1e2d5203ce..22bbc877d8 100644 --- a/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.markdown +++ b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.markdown @@ -15,7 +15,7 @@ Source code ----------- You can [download this from here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp) or +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp) or find it in the `samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp` of the OpenCV source code library. @@ -140,7 +140,7 @@ An application idea would be to determine the geometrical orientation present in example, let us find out if a text is horizontal or not? Looking at some text you'll notice that the text lines sort of form also horizontal lines and the letters form sort of vertical lines. These two main components of a text snippet may be also seen in case of the Fourier transform. Let us use -[this horizontal ](https://github.com/Itseez/opencv/tree/master/samples/data/imageTextN.png) and [this rotated](https://github.com/Itseez/opencv/tree/master/samples/data/imageTextR.png) +[this horizontal ](https://github.com/opencv/opencv/tree/master/samples/data/imageTextN.png) and [this rotated](https://github.com/opencv/opencv/tree/master/samples/data/imageTextR.png) image about a text. In case of the horizontal text: diff --git a/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.markdown b/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.markdown index 7576e5734d..10521338c0 100644 --- a/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.markdown +++ b/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.markdown @@ -16,7 +16,7 @@ Source code ----------- You can [download this from here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp) or find it in the +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp) or find it in the `samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp` of the OpenCV source code library. diff --git a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown index 1121caf400..409ebdbac1 100644 --- a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown +++ b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.markdown @@ -51,7 +51,7 @@ three major ways of going through an image pixel by pixel. To make things a litt will make the scanning for each image using all of these methods, and print out how long it took. You can download the full source code [here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp) or look it up in +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp) or look it up in the samples directory of OpenCV at the cpp tutorial code for the core section. Its basic usage is: @code{.bash} how_to_scan_images imageName.jpg intValueToReduce [G] diff --git a/doc/tutorials/core/how_to_use_ippa_conversion/how_to_use_ippa_conversion.markdown b/doc/tutorials/core/how_to_use_ippa_conversion/how_to_use_ippa_conversion.markdown index b851bbfe36..50f3b545ef 100644 --- a/doc/tutorials/core/how_to_use_ippa_conversion/how_to_use_ippa_conversion.markdown +++ b/doc/tutorials/core/how_to_use_ippa_conversion/how_to_use_ippa_conversion.markdown @@ -16,7 +16,7 @@ Code You may also find the source code in the `samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp` file of the OpenCV source library or -download it from [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp). +download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/ippasync/ippasync_sample.cpp). @include cpp/tutorial_code/core/ippasync/ippasync_sample.cpp diff --git a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.markdown b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.markdown index 3837e475ca..d28786a8b1 100644 --- a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.markdown +++ b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.markdown @@ -85,7 +85,7 @@ L = Mat(pI); A case study ------------ -Now that you have the basics done [here's](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp) +Now that you have the basics done [here's](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp) an example that mixes the usage of the C interface with the C++ one. You will also find it in the sample directory of the OpenCV source code library at the `samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` . @@ -132,7 +132,7 @@ output: You may observe a runtime instance of this on the [YouTube here](https://www.youtube.com/watch?v=qckm-zvo31w) and you can [download the source code from here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp) +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp) or find it in the `samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` of the OpenCV source code library. diff --git a/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown b/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown index 48b7b13a14..980ea78024 100644 --- a/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown +++ b/doc/tutorials/core/mat-mask-operations/mat_mask_operations.markdown @@ -133,7 +133,7 @@ For example: ![](images/resultMatMaskFilter2D.png) You can download this source code from [here -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp) or look in the +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp) or look in the OpenCV source code libraries sample directory at `samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp`. diff --git a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown index 65989744c2..9e290b88cc 100644 --- a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown +++ b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown @@ -258,7 +258,7 @@ OpenCV offers support for output of other common OpenCV data structures too via ![](images/MatBasicContainerOut15.png) Most of the samples here have been included in a small console application. You can download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp) or in the core section of the cpp samples. You can also find a quick video demonstration of this on diff --git a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown index be9b9762c6..92f3459d35 100644 --- a/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown +++ b/doc/tutorials/features2d/trackingmotion/corner_subpixeles/corner_subpixeles.markdown @@ -16,7 +16,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp) @code{.cpp} #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown index dd04afca07..7aba636746 100644 --- a/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown +++ b/doc/tutorials/features2d/trackingmotion/generic_corner_detector/generic_corner_detector.markdown @@ -20,7 +20,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp) @include cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp diff --git a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown index e4d9769952..23c1e3f904 100644 --- a/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown +++ b/doc/tutorials/features2d/trackingmotion/good_features_to_track/good_features_to_track.markdown @@ -15,7 +15,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp) @code{.cpp} #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown index add7db8a11..dc3070f544 100644 --- a/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown +++ b/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.markdown @@ -119,7 +119,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp) @code{.cpp} #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown b/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown index cf8aba954d..b2298968c7 100644 --- a/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown +++ b/doc/tutorials/gpu/gpu-basics-similarity/gpu_basics_similarity.markdown @@ -24,7 +24,7 @@ The source code You may also find the source code and these video file in the `samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity` folder of the OpenCV -source library or download it from [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp). +source library or download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp). The full source code is quite long (due to the controlling of the application via the command line arguments and performance measurement). Therefore, to avoid cluttering up these sections with those you'll find here only the functions itself. diff --git a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown index 831bba8a0d..e3786e607b 100644 --- a/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown +++ b/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown @@ -60,7 +60,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp) @include samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp Explanation diff --git a/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown b/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown index 43753ca6e1..2d17c3aade 100644 --- a/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown +++ b/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown @@ -94,7 +94,7 @@ Code - Applies 4 different kinds of filters (explained in Theory) and show the filtered images sequentially - **Downloadable code**: Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp) - **Code at glance:** @code{.cpp} #include "opencv2/imgproc.hpp" diff --git a/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown b/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown index fa4ff726f0..86575418be 100644 --- a/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown +++ b/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown @@ -70,13 +70,13 @@ Code - **Downloadable code**: -# Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp) for the basic version (explained in this tutorial). -# For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the skin area) you can check the [improved - demo](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp) + demo](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp) -# ...or you can always check out the classical - [camshiftdemo](https://github.com/Itseez/opencv/tree/master/samples/cpp/camshiftdemo.cpp) + [camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp) in samples. - **Code at glance:** diff --git a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown index a966d9087b..2907bf3e56 100644 --- a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown @@ -66,7 +66,7 @@ Code - Calculate the Histogram of each 1-channel plane by calling the function @ref cv::calcHist - Plot the three histograms in a window - **Downloadable code**: Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp) - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp diff --git a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown index 8b7399ff61..37ae5eac8a 100644 --- a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown @@ -44,7 +44,7 @@ Code histogram of the lower half base image and with the same base image histogram. - Display the numerical matching parameters obtained. - **Downloadable code**: Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp) - **Code at glance:** @include cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp diff --git a/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown b/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown index f3a2746de5..2d803cc7ea 100644 --- a/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown @@ -62,7 +62,7 @@ Code - Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist - Display the source and equalized images in a window. - **Downloadable code**: Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp) - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp diff --git a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown index c39fd159f0..3810bada43 100644 --- a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown +++ b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown @@ -96,7 +96,7 @@ Code - Localize the location with higher matching probability - Draw a rectangle around the area corresponding to the highest match - **Downloadable code**: Click - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp) - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp diff --git a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown index aa61992e59..c7bd63ed4f 100644 --- a/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown +++ b/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.markdown @@ -74,7 +74,7 @@ Code - Applies the mask obtained on the original image and display it in a window. -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown b/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown index d6cf3dfad3..dd4d785515 100644 --- a/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown +++ b/doc/tutorials/imgproc/imgtrans/copyMakeBorder/copyMakeBorder.markdown @@ -46,7 +46,7 @@ Code - The program finishes when the user presses 'ESC' -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/distance_transformation/distance_transform.markdown b/doc/tutorials/imgproc/imgtrans/distance_transformation/distance_transform.markdown index 1e49982241..0ba6b71a31 100644 --- a/doc/tutorials/imgproc/imgtrans/distance_transformation/distance_transform.markdown +++ b/doc/tutorials/imgproc/imgtrans/distance_transformation/distance_transform.markdown @@ -17,7 +17,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp). + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp). @include samples/cpp/tutorial_code/ImgTrans/imageSegmentation.cpp Explanation / Result diff --git a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown index 079bbed394..ef25b979f3 100644 --- a/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown +++ b/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.markdown @@ -62,7 +62,7 @@ Code - The filter output (with each kernel) will be shown during 500 milliseconds -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp) @code{.cpp} #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" diff --git a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown index e796c055c9..61f83aabce 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown +++ b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.markdown @@ -39,9 +39,9 @@ Code - Applies the *Hough Circle Transform* to the blurred image . - Display the detected circle in a window. --# The sample code that we will explain can be downloaded from [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/houghcircles.cpp). +-# The sample code that we will explain can be downloaded from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/houghcircles.cpp). A slightly fancier version (which shows trackbars for - changing the threshold values) can be found [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp). + changing the threshold values) can be found [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp). @include samples/cpp/houghcircles.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown index 8de662982e..584c3f8b68 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown +++ b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown @@ -95,9 +95,9 @@ Code - Applies either a *Standard Hough Line Transform* or a *Probabilistic Line Transform*. - Display the original image and the detected line in two windows. --# The sample code that we will explain can be downloaded from [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/houghlines.cpp). A slightly fancier version +-# The sample code that we will explain can be downloaded from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/houghlines.cpp). A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold - values) can be found [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp). + values) can be found [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp). @include samples/cpp/houghlines.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown b/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown index 104c2442f2..8976803c51 100644 --- a/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown +++ b/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.markdown @@ -51,7 +51,7 @@ Code - Display the result in a window -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/remap/remap.markdown b/doc/tutorials/imgproc/imgtrans/remap/remap.markdown index fd70f0133a..849157f077 100644 --- a/doc/tutorials/imgproc/imgtrans/remap/remap.markdown +++ b/doc/tutorials/imgproc/imgtrans/remap/remap.markdown @@ -52,7 +52,7 @@ Code - Wait for the user to exit the program -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown b/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown index 185f891c54..2d92fa0226 100644 --- a/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown +++ b/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.markdown @@ -108,7 +108,7 @@ Code bright on a darker background. -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp Explanation diff --git a/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.markdown b/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.markdown index 3612c32b54..934e8dba5e 100644 --- a/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.markdown +++ b/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.markdown @@ -89,7 +89,7 @@ Code - Waits until the user exits the program -# The tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp) + [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp) @include samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Explanation diff --git a/doc/tutorials/imgproc/morph_lines_detection/moprh_lines_detection.md b/doc/tutorials/imgproc/morph_lines_detection/moprh_lines_detection.md index 2fd260c8fd..23b748ddd1 100644 --- a/doc/tutorials/imgproc/morph_lines_detection/moprh_lines_detection.md +++ b/doc/tutorials/imgproc/morph_lines_detection/moprh_lines_detection.md @@ -48,7 +48,7 @@ A structuring element can have many common shapes, such as lines, diamonds, disk Code ---- -This tutorial code's is shown lines below. You can also download it from [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_3.cpp). +This tutorial code's is shown lines below. You can also download it from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_3.cpp). @include samples/cpp/tutorial_code/ImgProc/Morphology_3.cpp Explanation / Result diff --git a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown index e1eaed72bf..09331109d8 100644 --- a/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown +++ b/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.markdown @@ -80,7 +80,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp) @code{.cpp} #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" diff --git a/doc/tutorials/imgproc/pyramids/pyramids.markdown b/doc/tutorials/imgproc/pyramids/pyramids.markdown index 1a07d8c56a..0bb5160fbb 100644 --- a/doc/tutorials/imgproc/pyramids/pyramids.markdown +++ b/doc/tutorials/imgproc/pyramids/pyramids.markdown @@ -66,7 +66,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp) @include samples/cpp/tutorial_code/ImgProc/Pyramids.cpp diff --git a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown index 499ad916c9..fef66fb665 100644 --- a/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.markdown @@ -16,7 +16,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp Explanation diff --git a/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.markdown b/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.markdown index 5dcf69ca22..e7b3a94553 100644 --- a/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.markdown @@ -16,7 +16,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp Explanation diff --git a/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.markdown b/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.markdown index 71329db1af..11d1d9f476 100644 --- a/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.markdown @@ -16,7 +16,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp Explanation diff --git a/doc/tutorials/imgproc/shapedescriptors/hull/hull.markdown b/doc/tutorials/imgproc/shapedescriptors/hull/hull.markdown index 5af9de16a1..38df72029e 100644 --- a/doc/tutorials/imgproc/shapedescriptors/hull/hull.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/hull/hull.markdown @@ -15,7 +15,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp diff --git a/doc/tutorials/imgproc/shapedescriptors/moments/moments.markdown b/doc/tutorials/imgproc/shapedescriptors/moments/moments.markdown index 9398701e4c..3ef4c13615 100644 --- a/doc/tutorials/imgproc/shapedescriptors/moments/moments.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/moments/moments.markdown @@ -17,7 +17,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp Explanation diff --git a/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.markdown b/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.markdown index 03f612844c..4ffb98be48 100644 --- a/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.markdown +++ b/doc/tutorials/imgproc/shapedescriptors/point_polygon_test/point_polygon_test.markdown @@ -15,7 +15,7 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp) @include samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp Explanation diff --git a/doc/tutorials/imgproc/threshold/threshold.markdown b/doc/tutorials/imgproc/threshold/threshold.markdown index b78ae9cd4c..f0bc735ab6 100644 --- a/doc/tutorials/imgproc/threshold/threshold.markdown +++ b/doc/tutorials/imgproc/threshold/threshold.markdown @@ -97,7 +97,7 @@ Code ---- The tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Threshold.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Threshold.cpp) @include samples/cpp/tutorial_code/ImgProc/Threshold.cpp Explanation diff --git a/doc/tutorials/imgproc/threshold_inRange/threshold_inRange.markdown b/doc/tutorials/imgproc/threshold_inRange/threshold_inRange.markdown index edafc06818..101fa01d43 100644 --- a/doc/tutorials/imgproc/threshold_inRange/threshold_inRange.markdown +++ b/doc/tutorials/imgproc/threshold_inRange/threshold_inRange.markdown @@ -19,7 +19,7 @@ Code ---- The tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Threshold_inRange.cpp) +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Threshold_inRange.cpp) @include samples/cpp/tutorial_code/ImgProc/Threshold_inRange.cpp Explanation diff --git a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown index b7751764a9..3dab6e8c98 100644 --- a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown +++ b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown @@ -17,7 +17,7 @@ If you need help with anything of the above, you may refer to our @ref tutorial_ This tutorial also assumes you have an Android operated device with OpenCL enabled. The related source code is located within OpenCV samples at -[opencv/samples/android/tutorial-4-opencl](https://github.com/Itseez/opencv/tree/master/samples/android/tutorial-4-opencl/) directory. +[opencv/samples/android/tutorial-4-opencl](https://github.com/opencv/opencv/tree/master/samples/android/tutorial-4-opencl/) directory. Preface ------- @@ -244,7 +244,7 @@ As you can see, inheritors for `Camera` and `Camera2` APIs should implement the @endcode Let's leave the details of their implementation beyond of this tutorial, please refer the -[source code](https://github.com/Itseez/opencv/tree/master/samples/android/tutorial-4-opencl/) to see them. +[source code](https://github.com/opencv/opencv/tree/master/samples/android/tutorial-4-opencl/) to see them. Preview Frames modification --------------------------- diff --git a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown index 5af960843c..7765e1af95 100644 --- a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown +++ b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.markdown @@ -40,7 +40,7 @@ I'm assuming you already installed [xcode](https://developer.apple.com/xcode/), @code{.bash} cd ~/ mkdir opt -git clone https://github.com/Itseez/opencv.git +git clone https://github.com/opencv/opencv.git cd opencv git checkout 2.4 mkdir build diff --git a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown index 1b9dc30ea5..3ef08f8a39 100644 --- a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown +++ b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.markdown @@ -33,7 +33,7 @@ Getting OpenCV Source Code -------------------------- You can use the latest stable OpenCV version available in *sourceforge* or you can grab the latest -snapshot from our [Git repository](https://github.com/Itseez/opencv.git). +snapshot from our [Git repository](https://github.com/opencv/opencv.git). ### Getting the Latest Stable OpenCV Version @@ -42,12 +42,12 @@ snapshot from our [Git repository](https://github.com/Itseez/opencv.git). ### Getting the Cutting-edge OpenCV from the Git Repository -Launch Git client and clone [OpenCV repository](http://github.com/itseez/opencv) +Launch Git client and clone [OpenCV repository](http://github.com/opencv/opencv) In Linux it can be achieved with the following command in Terminal: @code{.bash} cd ~/ -git clone https://github.com/Itseez/opencv.git +git clone https://github.com/opencv/opencv.git @endcode Building OpenCV diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown b/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown index 9e8048d168..c6e8c06f7c 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.markdown @@ -36,7 +36,7 @@ from the [OpenCV SourceForge repository](http://sourceforge.net/projects/opencvl sources. Another option to get OpenCV sources is to clone [OpenCV git -repository](https://github.com/Itseez/opencv/). In order to build OpenCV with Java bindings you need +repository](https://github.com/opencv/opencv/). In order to build OpenCV with Java bindings you need JDK (Java Development Kit) (we recommend [Oracle/Sun JDK 6 or 7](http://www.oracle.com/technetwork/java/javase/downloads/)), [Apache Ant](http://ant.apache.org/) and Python v2.6 or higher to be installed. @@ -45,7 +45,7 @@ and Python v2.6 or higher to be installed. Let's build OpenCV: @code{.bash} -git clone git://github.com/Itseez/opencv.git +git clone git://github.com/opencv/opencv.git cd opencv git checkout 2.4 mkdir build diff --git a/doc/tutorials/introduction/display_image/display_image.markdown b/doc/tutorials/introduction/display_image/display_image.markdown index c4a1f1df59..f0eea98ee7 100644 --- a/doc/tutorials/introduction/display_image/display_image.markdown +++ b/doc/tutorials/introduction/display_image/display_image.markdown @@ -14,7 +14,7 @@ Source Code ----------- Download the source code from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp). +[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp). @include cpp/tutorial_code/introduction/display_image/display_image.cpp diff --git a/doc/tutorials/introduction/ios_install/ios_install.markdown b/doc/tutorials/introduction/ios_install/ios_install.markdown index 00faf685f5..9a82e15205 100644 --- a/doc/tutorials/introduction/ios_install/ios_install.markdown +++ b/doc/tutorials/introduction/ios_install/ios_install.markdown @@ -9,13 +9,13 @@ Required Packages ### Getting the Cutting-edge OpenCV from Git Repository -Launch GIT client and clone OpenCV repository from [here](http://github.com/itseez/opencv) +Launch GIT client and clone OpenCV repository from [here](http://github.com/opencv/opencv) In MacOS it can be done using the following command in Terminal: @code{.bash} cd ~/ -git clone https://github.com/Itseez/opencv.git +git clone https://github.com/opencv/opencv.git @endcode Building OpenCV from Source, using CMake and Command Line diff --git a/doc/tutorials/introduction/linux_install/linux_install.markdown b/doc/tutorials/introduction/linux_install/linux_install.markdown index b1868f82d7..387902dfec 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.markdown +++ b/doc/tutorials/introduction/linux_install/linux_install.markdown @@ -28,7 +28,7 @@ Getting OpenCV Source Code -------------------------- You can use the latest stable OpenCV version or you can grab the latest snapshot from our [Git -repository](https://github.com/Itseez/opencv.git). +repository](https://github.com/opencv/opencv.git). ### Getting the Latest Stable OpenCV Version @@ -37,14 +37,14 @@ repository](https://github.com/Itseez/opencv.git). ### Getting the Cutting-edge OpenCV from the Git Repository -Launch Git client and clone [OpenCV repository](http://github.com/itseez/opencv). If you need -modules from [OpenCV contrib repository](http://github.com/itseez/opencv_contrib) then clone it too. +Launch Git client and clone [OpenCV repository](http://github.com/opencv/opencv). If you need +modules from [OpenCV contrib repository](http://github.com/opencv/opencv_contrib) then clone it too. For example @code{.bash} cd ~/ -git clone https://github.com/Itseez/opencv.git -git clone https://github.com/Itseez/opencv_contrib.git +git clone https://github.com/opencv/opencv.git +git clone https://github.com/opencv/opencv_contrib.git @endcode Building OpenCV from Source Using CMake --------------------------------------- @@ -114,11 +114,11 @@ Building OpenCV from Source Using CMake -# [optional] Running tests - Get the required test data from [OpenCV extra - repository](https://github.com/Itseez/opencv_extra). + repository](https://github.com/opencv/opencv_extra). For example @code{.bash} - git clone https://github.com/Itseez/opencv_extra.git + git clone https://github.com/opencv/opencv_extra.git @endcode - set OPENCV_TEST_DATA_PATH environment variable to \. - execute tests from build directory. diff --git a/doc/tutorials/introduction/transition_guide/transition_guide.markdown b/doc/tutorials/introduction/transition_guide/transition_guide.markdown index b0bc44344c..3b9620a086 100644 --- a/doc/tutorials/introduction/transition_guide/transition_guide.markdown +++ b/doc/tutorials/introduction/transition_guide/transition_guide.markdown @@ -12,7 +12,7 @@ OpenCV 3.0 introduced many new algorithms and features comparing to version 2.4. This section describes most notable changes in general, all details and examples of transition actions are in the next part of the document. ##### Contrib repository - + This is a place for all new, experimental and non-free algorithms. It does not receive so much attention from the support team comparing to main repository, but the community makes an effort to keep it in a good shape. diff --git a/doc/tutorials/introduction/windows_install/windows_install.markdown b/doc/tutorials/introduction/windows_install/windows_install.markdown index c8808b493a..22c9d99683 100644 --- a/doc/tutorials/introduction/windows_install/windows_install.markdown +++ b/doc/tutorials/introduction/windows_install/windows_install.markdown @@ -43,7 +43,7 @@ These videos above are long-obsolete and contain inaccurate information. Be care solutions described in those videos are no longer supported and may even break your install. If you are building your own libraries you can take the source files from our [Git -repository](https://github.com/Itseez/opencv.git). +repository](https://github.com/opencv/opencv.git). Building the OpenCV library from scratch requires a couple of tools installed beforehand: @@ -114,7 +114,7 @@ libraries). If you do not need the support for some of these you can just freely you're doing -- it's OK. -# Clone the repository to the selected directory. After clicking *Clone* button, a window will appear where you can select from what repository you want to download source files - () and to what directory (`D:/OpenCV`). + () and to what directory (`D:/OpenCV`). -# Push the OK button and be patient as the repository is quite a heavy download. It will take some time depending on your Internet connection. diff --git a/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.markdown b/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.markdown index 78776af33e..3be7f5bb87 100644 --- a/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.markdown +++ b/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.markdown @@ -189,7 +189,7 @@ Test it! -------- Now to try this out download our little test [source code -](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp) +](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp) or get it from the sample code folder of the OpenCV sources. Add this to your project and build it. Here's its content: @@ -205,7 +205,7 @@ the *IDE* the console window will not close once finished. It will wait for a ke This is important to remember when you code inside the code open and save commands. You're resources will be saved ( and queried for at opening!!!) relatively to your working directory. This is unless you give a full, explicit path as parameter for the I/O functions. In the code above we open [this -OpenCV logo](https://github.com/Itseez/opencv/tree/master/samples/data/opencv-logo.png). Before starting up the application make sure you place +OpenCV logo](https://github.com/opencv/opencv/tree/master/samples/data/opencv-logo.png). Before starting up the application make sure you place the image file in your current working directory. Modify the image file name inside the code to try it out on other images too. Run it and voil á: diff --git a/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown b/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown index 78ed547809..82274efedd 100644 --- a/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown +++ b/doc/tutorials/ml/introduction_to_pca/introduction_to_pca.markdown @@ -92,10 +92,10 @@ Source Code ----------- This tutorial code's is shown lines below. You can also download it from - [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp). + [here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp). @include cpp/tutorial_code/ml/introduction_to_pca/introduction_to_pca.cpp -@note Another example using PCA for dimensionality reduction while maintaining an amount of variance can be found at [opencv_source_code/samples/cpp/pca.cpp](https://github.com/Itseez/opencv/tree/master/samples/cpp/pca.cpp) +@note Another example using PCA for dimensionality reduction while maintaining an amount of variance can be found at [opencv_source_code/samples/cpp/pca.cpp](https://github.com/opencv/tree/master/samples/cpp/pca.cpp) Explanation ----------- diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index 52b544dd06..1a18870079 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -87,7 +87,7 @@ Source Code ----------- You may also find the source code in `samples/cpp/tutorial_code/ml/non_linear_svms` folder of the OpenCV source library or -[download it from here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp). +[download it from here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp). @note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms) diff --git a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown index 382046fe34..ec27dc2731 100644 --- a/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown +++ b/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.markdown @@ -18,9 +18,9 @@ Code ---- This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp) +[here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp) . The second version (using LBP for face detection) can be [found -here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp) +here](https://github.com/opencv/tree/master/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp) @code{.cpp} #include "opencv2/objdetect.hpp" #include "opencv2/highgui.hpp" diff --git a/doc/tutorials/video/background_subtraction/background_subtraction.markdown b/doc/tutorials/video/background_subtraction/background_subtraction.markdown index f9b7eebf15..8ed68f5e25 100644 --- a/doc/tutorials/video/background_subtraction/background_subtraction.markdown +++ b/doc/tutorials/video/background_subtraction/background_subtraction.markdown @@ -45,7 +45,7 @@ Two different methods are used to generate two foreground masks: -# @ref cv::BackgroundSubtractorMOG2 The results as well as the input data are shown on the screen. -The source file can be downloaded [here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/video/bg_sub.cpp). +The source file can be downloaded [here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/video/bg_sub.cpp). @include samples/cpp/tutorial_code/video/bg_sub.cpp diff --git a/doc/tutorials/videoio/intelperc.markdown b/doc/tutorials/videoio/intelperc.markdown index b5f2ed64ed..188a69e659 100644 --- a/doc/tutorials/videoio/intelperc.markdown +++ b/doc/tutorials/videoio/intelperc.markdown @@ -78,5 +78,5 @@ there are two flags that should be used to set/get property of the needed genera flag value is assumed by default if neither of the two possible values of the property is set. For more information please refer to the example of usage -[intelperc_capture.cpp](https://github.com/Itseez/opencv/tree/master/samples/cpp/intelperc_capture.cpp) +[intelperc_capture.cpp](https://github.com/opencv/tree/master/samples/cpp/intelperc_capture.cpp) in opencv/samples/cpp folder. diff --git a/doc/tutorials/videoio/kinect_openni.markdown b/doc/tutorials/videoio/kinect_openni.markdown index c9c33a2a05..82ec13ef91 100644 --- a/doc/tutorials/videoio/kinect_openni.markdown +++ b/doc/tutorials/videoio/kinect_openni.markdown @@ -134,5 +134,5 @@ property. The following properties of cameras available through OpenNI interface - CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION For more information please refer to the example of usage -[openni_capture.cpp](https://github.com/Itseez/opencv/tree/master/samples/cpp/openni_capture.cpp) in +[openni_capture.cpp](https://github.com/opencv/tree/master/samples/cpp/openni_capture.cpp) in opencv/samples/cpp folder. diff --git a/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown b/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown index 9dbff286ca..fdaad3aa26 100644 --- a/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown +++ b/doc/tutorials/videoio/video-input-psnr-ssim/video_input_psnr_ssim.markdown @@ -20,8 +20,8 @@ As a test case where to show off these using OpenCV I've created a small program video files and performs a similarity check between them. This is something you could use to check just how well a new video compressing algorithms works. Let there be a reference (original) video like [this small Megamind clip -](https://github.com/Itseez/opencv/tree/master/samples/data/Megamind.avi) and [a compressed -version of it ](https://github.com/Itseez/opencv/tree/master/samples/data/Megamind_bugy.avi). +](https://github.com/opencv/opencv/tree/master/samples/data/Megamind.avi) and [a compressed +version of it ](https://github.com/opencv/opencv/tree/master/samples/data/Megamind_bugy.avi). You may also find the source code and these video file in the `samples/data` folder of the OpenCV source library. diff --git a/doc/tutorials/videoio/video-write/video_write.markdown b/doc/tutorials/videoio/video-write/video_write.markdown index 399ac7a1e2..38c9151248 100644 --- a/doc/tutorials/videoio/video-write/video_write.markdown +++ b/doc/tutorials/videoio/video-write/video_write.markdown @@ -31,7 +31,7 @@ The source code You may also find the source code and these video file in the `samples/cpp/tutorial_code/videoio/video-write/` folder of the OpenCV source library or [download it -from here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/videoio/video-write/video-write.cpp). +from here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/videoio/video-write/video-write.cpp). @include cpp/tutorial_code/videoio/video-write/video-write.cpp diff --git a/doc/tutorials/viz/creating_widgets/creating_widgets.markdown b/doc/tutorials/viz/creating_widgets/creating_widgets.markdown index ea84fe3aa0..4e4f6e5aed 100644 --- a/doc/tutorials/viz/creating_widgets/creating_widgets.markdown +++ b/doc/tutorials/viz/creating_widgets/creating_widgets.markdown @@ -12,7 +12,7 @@ In this tutorial you will learn how to Code ---- -You can download the code from [here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/viz/creating_widgets.cpp). +You can download the code from [here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/viz/creating_widgets.cpp). @include samples/cpp/tutorial_code/viz/creating_widgets.cpp Explanation diff --git a/doc/tutorials/viz/launching_viz/launching_viz.markdown b/doc/tutorials/viz/launching_viz/launching_viz.markdown index 25914dcb30..07719c67eb 100644 --- a/doc/tutorials/viz/launching_viz/launching_viz.markdown +++ b/doc/tutorials/viz/launching_viz/launching_viz.markdown @@ -14,7 +14,7 @@ In this tutorial you will learn how to Code ---- -You can download the code from [here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/viz/launching_viz.cpp). +You can download the code from [here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/viz/launching_viz.cpp). @include samples/cpp/tutorial_code/viz/launching_viz.cpp Explanation diff --git a/doc/tutorials/viz/transformations/transformations.markdown b/doc/tutorials/viz/transformations/transformations.markdown index 8b9c1f6722..512ce80bdb 100644 --- a/doc/tutorials/viz/transformations/transformations.markdown +++ b/doc/tutorials/viz/transformations/transformations.markdown @@ -13,7 +13,7 @@ In this tutorial you will learn how to Code ---- -You can download the code from [here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/viz/transformations.cpp). +You can download the code from [here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/viz/transformations.cpp). @include samples/cpp/tutorial_code/viz/transformations.cpp Explanation diff --git a/doc/tutorials/viz/widget_pose/widget_pose.markdown b/doc/tutorials/viz/widget_pose/widget_pose.markdown index 7e6a1b9da2..382ae98556 100644 --- a/doc/tutorials/viz/widget_pose/widget_pose.markdown +++ b/doc/tutorials/viz/widget_pose/widget_pose.markdown @@ -13,7 +13,7 @@ In this tutorial you will learn how to Code ---- -You can download the code from [here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/viz/widget_pose.cpp). +You can download the code from [here ](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/viz/widget_pose.cpp). @include samples/cpp/tutorial_code/viz/widget_pose.cpp Explanation diff --git a/modules/core/doc/cuda.markdown b/modules/core/doc/cuda.markdown index fb648e25dd..ea85007a34 100644 --- a/modules/core/doc/cuda.markdown +++ b/modules/core/doc/cuda.markdown @@ -82,4 +82,4 @@ Block Matching algorithm has been successfully parallelized using the following 3. Merge the results into a single disparity map. With this algorithm, a dual GPU gave a 180% performance increase comparing to the single Fermi GPU. -For a source code example, see . +For a source code example, see . diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index a515c15b33..7f963a5cdf 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -425,7 +425,7 @@ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); @param winname Name of the window. @param onMouse Mouse callback. See OpenCV samples, such as -, on how to specify and +, on how to specify and use the callback. @param userdata The optional parameter passed to the callback. */ diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 6587b3d77a..87d7ec3ac5 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -91,7 +91,7 @@ compensate for the differences in the size of areas. The sums of pixel values ov regions are calculated rapidly using integral images (see below and the integral description). To see the object detector at work, have a look at the facedetect demo: - + The following reference is for the detection part only. There is a separate application called opencv_traincascade that can train a cascade of boosted classifiers from a set of samples. diff --git a/modules/python/test/test_digits.py b/modules/python/test/test_digits.py index 2d5c900438..c7ac9964b7 100644 --- a/modules/python/test/test_digits.py +++ b/modules/python/test/test_digits.py @@ -58,7 +58,7 @@ def deskew(img): class StatModel(object): def load(self, fn): - self.model.load(fn) # Known bug: https://github.com/Itseez/opencv/issues/4969 + self.model.load(fn) # Known bug: https://github.com/opencv/opencv/issues/4969 def save(self, fn): self.model.save(fn) diff --git a/modules/python/test/test_gaussian_mix.py b/modules/python/test/test_gaussian_mix.py index cfd33ece02..78a29ceb4e 100644 --- a/modules/python/test/test_gaussian_mix.py +++ b/modules/python/test/test_gaussian_mix.py @@ -43,7 +43,7 @@ class gaussian_mix_test(NewOpenCVTests): em.setCovarianceMatrixType(cv2.ml.EM_COV_MAT_GENERIC) em.trainEM(points) means = em.getMeans() - covs = em.getCovs() # Known bug: https://github.com/Itseez/opencv/pull/4232 + covs = em.getCovs() # Known bug: https://github.com/opencv/opencv/pull/4232 found_distrs = zip(means, covs) matches_count = 0 diff --git a/modules/python/test/tests_common.py b/modules/python/test/tests_common.py index 67b5bea2f7..17ef0dc923 100644 --- a/modules/python/test/tests_common.py +++ b/modules/python/test/tests_common.py @@ -21,7 +21,7 @@ class NewOpenCVTests(unittest.TestCase): repoPath = None extraTestDataPath = None # github repository url - repoUrl = 'https://raw.github.com/Itseez/opencv/master' + repoUrl = 'https://raw.github.com/opencv/opencv/master' def get_sample(self, filename, iscolor = cv2.IMREAD_COLOR): if not filename in self.image_cache: diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index 0acb3d3f1e..c462c67ce5 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -614,7 +614,7 @@ public: Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the correct way of retrieving data from it is to call VideoCapture::grab first and then call VideoCapture::retrieve one or more times with different values of the channel parameter. See - + */ CV_WRAP virtual bool grab(); diff --git a/modules/videoio/src/cap_libv4l.cpp b/modules/videoio/src/cap_libv4l.cpp index 214146144a..3ff564b07f 100644 --- a/modules/videoio/src/cap_libv4l.cpp +++ b/modules/videoio/src/cap_libv4l.cpp @@ -16,7 +16,7 @@ For Release: OpenCV-Linux Beta4 opencv-0.9.6 Tested On: LMLBT44 with 8 video inputs Problems? Post your questions at answers.opencv.org, Report bugs at code.opencv.org, - Submit your fixes at https://github.com/Itseez/opencv/ + Submit your fixes at https://github.com/opencv/opencv/ Patched Comments: TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4 diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 227b4aa335..01a250b41e 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -16,7 +16,7 @@ For Release: OpenCV-Linux Beta4 opencv-0.9.6 Tested On: LMLBT44 with 8 video inputs Problems? Post your questions at answers.opencv.org, Report bugs at code.opencv.org, - Submit your fixes at https://github.com/Itseez/opencv/ + Submit your fixes at https://github.com/opencv/opencv/ Patched Comments: TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4 diff --git a/platforms/winrt/readme.txt b/platforms/winrt/readme.txt index c35d18d21f..2fb4ce1f54 100644 --- a/platforms/winrt/readme.txt +++ b/platforms/winrt/readme.txt @@ -124,7 +124,7 @@ Running tests for Windows Store =============================== 1. You might need to install this if you haven't already: http://www.microsoft.com/en-US/download/details.aspx?id=40784 -2. Set OPENCV_TEST_DATA_PATH environment variable to location of opencv_extra/testdata (cloning of https://github.com/Itseez/opencv_extra repo required) to get tests work correctly. Also, set OPENCV_PERF_VALIDATION_DIR environment variable in case you are planning to have place where to store performance test results and compare them with the future test runs. +2. Set OPENCV_TEST_DATA_PATH environment variable to location of opencv_extra/testdata (cloning of https://github.com/opencv/opencv_extra repo required) to get tests work correctly. Also, set OPENCV_PERF_VALIDATION_DIR environment variable in case you are planning to have place where to store performance test results and compare them with the future test runs. 3. In case you'd like to adjust some flags that are defaulted by setup_winrt script, go to "Manual build" section. Otherwise go to platforms/winrt and execute diff --git a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrationActivity.java b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrationActivity.java index aa90504054..af0853a7cc 100644 --- a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrationActivity.java +++ b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrationActivity.java @@ -2,7 +2,7 @@ // http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html // // It uses standard OpenCV asymmetric circles grid pattern 11x4: -// https://github.com/Itseez/opencv/blob/2.4/doc/acircles_pattern.png. +// https://github.com/opencv/opencv/blob/2.4/doc/acircles_pattern.png. // The results are the camera matrix and 5 distortion coefficients. // // Tap on highlighted pattern to capture pattern corners for calibration. diff --git a/samples/cpp/facial_features.cpp b/samples/cpp/facial_features.cpp index 3ed6a442f9..6dbef75c49 100644 --- a/samples/cpp/facial_features.cpp +++ b/samples/cpp/facial_features.cpp @@ -89,10 +89,10 @@ static void help() "\tThis will detect only the face in image.jpg.\n"; cout << " \n\nThe classifiers for face and eyes can be downloaded from : " - " \nhttps://github.com/Itseez/opencv/tree/master/data/haarcascades"; + " \nhttps://github.com/opencv/opencv/tree/master/data/haarcascades"; cout << "\n\nThe classifiers for nose and mouth can be downloaded from : " - " \nhttps://github.com/Itseez/opencv_contrib/tree/master/modules/face/data/cascades\n"; + " \nhttps://github.com/opencv/opencv_contrib/tree/master/modules/face/data/cascades\n"; } static void detectFaces(Mat& img, vector >& faces, string cascade_path) diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index 025e1d3b60..000928c1cf 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -19,7 +19,7 @@ Online docs: http://docs.opencv.org Q&A forum: http://answers.opencv.org Issue tracker: http://code.opencv.org - GitHub: https://github.com/Itseez/opencv/ + GitHub: https://github.com/opencv/opencv/ ************************************************** */ #include "opencv2/calib3d.hpp" diff --git a/samples/python/digits.py b/samples/python/digits.py index 04397a1431..5cc98b713c 100755 --- a/samples/python/digits.py +++ b/samples/python/digits.py @@ -71,7 +71,7 @@ def deskew(img): class StatModel(object): def load(self, fn): - self.model.load(fn) # Known bug: https://github.com/Itseez/opencv/issues/4969 + self.model.load(fn) # Known bug: https://github.com/opencv/opencv/issues/4969 def save(self, fn): self.model.save(fn) diff --git a/samples/python/digits_video.py b/samples/python/digits_video.py index c85deb6d0a..74b9d6993b 100755 --- a/samples/python/digits_video.py +++ b/samples/python/digits_video.py @@ -32,7 +32,7 @@ def main(): model = cv2.ml.SVM_load(classifier_fn) else: model = cv2.ml.SVM_create() - model.load_(classifier_fn) #Known bug: https://github.com/Itseez/opencv/issues/4969 + model.load_(classifier_fn) #Known bug: https://github.com/opencv/opencv/issues/4969 while True: ret, frame = cap.read() diff --git a/samples/python/find_obj.py b/samples/python/find_obj.py index 09457b80be..a77024c4c0 100755 --- a/samples/python/find_obj.py +++ b/samples/python/find_obj.py @@ -3,7 +3,7 @@ ''' Feature-based image matching sample. -Note, that you will need the https://github.com/Itseez/opencv_contrib repo for SIFT and SURF +Note, that you will need the https://github.com/opencv/opencv_contrib repo for SIFT and SURF USAGE find_obj.py [--feature=[-flann]] [ ] diff --git a/samples/python/gaussian_mix.py b/samples/python/gaussian_mix.py index b0c28748f2..64fbe23462 100755 --- a/samples/python/gaussian_mix.py +++ b/samples/python/gaussian_mix.py @@ -50,7 +50,7 @@ if __name__ == '__main__': em.setCovarianceMatrixType(cv2.ml.EM_COV_MAT_GENERIC) em.trainEM(points) means = em.getMeans() - covs = em.getCovs() # Known bug: https://github.com/Itseez/opencv/pull/4232 + covs = em.getCovs() # Known bug: https://github.com/opencv/opencv/pull/4232 found_distrs = zip(means, covs) print('ready!\n') diff --git a/samples/python/video_v4l2.py b/samples/python/video_v4l2.py index 9ef958e69d..eed22d11b8 100644 --- a/samples/python/video_v4l2.py +++ b/samples/python/video_v4l2.py @@ -27,7 +27,7 @@ font = cv2.FONT_HERSHEY_SIMPLEX color = (0, 255, 0) cap = cv2.VideoCapture(0) -cap.set(cv2.CAP_PROP_AUTOFOCUS, False) # Known bug: https://github.com/Itseez/opencv/pull/5474 +cap.set(cv2.CAP_PROP_AUTOFOCUS, False) # Known bug: https://github.com/opencv/opencv/pull/5474 cv2.namedWindow("Video") From 1f26e7347841fa9c65729a4432cff4bb1e7d184d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Jul 2016 15:47:50 +0300 Subject: [PATCH 049/153] ffmpeg: try to load ffmpeg wrapper dll from the current module directory --- modules/videoio/src/cap_ffmpeg.cpp | 48 ++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg.cpp b/modules/videoio/src/cap_ffmpeg.cpp index b4348eaa05..772996e505 100644 --- a/modules/videoio/src/cap_ffmpeg.cpp +++ b/modules/videoio/src/cap_ffmpeg.cpp @@ -41,6 +41,8 @@ #include "precomp.hpp" +#include + #if defined HAVE_FFMPEG && !defined WIN32 #include "cap_ffmpeg_impl.hpp" #else @@ -59,6 +61,17 @@ static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0; static cv::Mutex _icvInitFFMPEG_mutex; +#if defined WIN32 || defined _WIN32 +static const HMODULE cv_GetCurrentModule() +{ + HMODULE h = 0; + ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(cv_GetCurrentModule), + &h); + return h; +} +#endif + class icvInitFFMPEG { public: @@ -95,14 +108,39 @@ private: icvFFOpenCV = LoadPackagedLibrary( module_name, 0 ); # else - const char* module_name = "opencv_ffmpeg" - CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION) + const std::wstring module_name = L"opencv_ffmpeg" + CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION) #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) - "_64" + L"_64" #endif - ".dll"; + L".dll"; - icvFFOpenCV = LoadLibrary( module_name ); + const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR"); + std::wstring module_path = + ffmpeg_env_path + ? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name) + : module_name; + + icvFFOpenCV = LoadLibraryW(module_path.c_str()); + if(!icvFFOpenCV && !ffmpeg_env_path) + { + HMODULE m = cv_GetCurrentModule(); + if (m) + { + wchar_t path[MAX_PATH]; + size_t sz = GetModuleFileNameW(m, path, sizeof(path)); + if (sz > 0 && ERROR_SUCCESS == GetLastError()) + { + wchar_t* s = wcsrchr(path, L'\\'); + if (s) + { + s[0] = 0; + module_path = (std::wstring(path) + L"\\") + module_name; + icvFFOpenCV = LoadLibraryW(module_path.c_str()); + } + } + } + } # endif if( icvFFOpenCV ) From 74b83cfce59318c90683fb5daa73fc8d4bea118e Mon Sep 17 00:00:00 2001 From: Oliver Schreer Date: Fri, 22 May 2015 10:39:01 +0200 Subject: [PATCH 050/153] Modified and improved the method for chessboard detection. It is now faster and detects chessboards under difficult lighting condition as well as when the chessboard has strong out of plane rotations --- .../include/opencv2/calib3d/calib3d.hpp | 9 + modules/calib3d/src/calibinit.cpp | 652 +++++++++++++----- modules/calib3d/src/checkchessboard.cpp | 98 ++- 3 files changed, 585 insertions(+), 174 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp index b3da45edd5..517372edc5 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp @@ -46,3 +46,12 @@ #endif #include "opencv2/calib3d.hpp" +// Performs a fast check if a chessboard is in the input image. This is a workaround to +// a problem of cvFindChessboardCorners being slow on images with no chessboard. +// This method works using a binary image as input +// - src: input binary image +// - size: chessboard size +// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, +// 0 if there is no chessboard, -1 in case of error +CVAPI(int) cvCheckChessboardBinary(IplImage* src, CvSize size); + diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index d6b4923d11..0f4676da97 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -59,11 +59,22 @@ \************************************************************************************/ +/************************************************************************************\ + This version adds a new and improved variant of chessboard corner detection + that works better in poor lighting condition. It is based on work from + Oliver Schreer and Stefano Masneri. This method works faster than the previous + one and reverts back to the older method in case no chessboard detection is + possible. Overall performance improves also because now the method avoids + performing the same computation multiple times when not necessary. + +\************************************************************************************/ + #include "precomp.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/calib3d/calib3d_c.h" #include "circlesgrid.hpp" #include +#include //#define ENABLE_TRIM_COL_ROW @@ -191,6 +202,202 @@ static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ); +/***************************************************************************************************/ +//COMPUTE INTENSITY HISTOGRAM OF INPUT IMAGE +static int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector& piHist ); +//SMOOTH HISTOGRAM USING WINDOW OF SIZE 2*iWidth+1 +static int icvSmoothHistogram( const std::vector& piHist, std::vector& piHistSmooth, int iWidth ); +//COMPUTE FAST HISTOGRAM GRADIENT +static int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ); +//PERFORM SMART IMAGE THRESHOLDING BASED ON ANALYSIS OF INTENSTY HISTOGRAM +static bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows ); +/***************************************************************************************************/ +int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector& piHist ) +{ + int iVal; + + // sum up all pixel in row direction and divide by number of columns + for ( int j=0; j& piHist, std::vector& piHistSmooth, int iWidth ) +{ + int iIdx; + for ( int i=0; i<256; i++) + { + int iSmooth = 0; + for ( int ii=-iWidth; ii<=iWidth; ii++) + { + iIdx = i+ii; + if (iIdx > 0 && iIdx < 256) + { + iSmooth += piHist[iIdx]; + } + } + piHistSmooth[i] = iSmooth/(2*iWidth+1); + } + return 0; +} +/***************************************************************************************************/ +int icvGradientOfHistogram( const std::vector& piHist, std::vector& piHistGrad ) +{ + piHistGrad[0] = 0; + for ( int i=1; i<255; i++) + { + piHistGrad[i] = piHist[i-1] - piHist[i+1]; + if ( abs(piHistGrad[i]) < 100 ) + { + if ( piHistGrad[i-1] == 0) + piHistGrad[i] = -100; + else + piHistGrad[i] = piHistGrad[i-1]; + } + } + return 0; +} +/***************************************************************************************************/ +bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows ) +{ + int iMaxPix = iCols*iRows; + int iMaxPix1 = iMaxPix/100; + const int iNumBins = 256; + std::vector piHistIntensity(iNumBins, 0); + std::vector piHistSmooth(iNumBins, 0); + std::vector piHistGrad(iNumBins, 0); + std::vector piAccumSum(iNumBins, 0); + std::vector piMaxPos(20, 0); + int iThresh = 0; + int iIdx; + int iWidth = 1; + + icvGetIntensityHistogram( pucImg, iCols, iRows, piHistIntensity ); + + // get accumulated sum starting from bright + piAccumSum[iNumBins-1] = piHistIntensity[iNumBins-1]; + for ( int i=iNumBins-2; i>=0; i-- ) + { + piAccumSum[i] = piHistIntensity[i] + piAccumSum[i+1]; + } + + // first smooth the distribution + icvSmoothHistogram( piHistIntensity, piHistSmooth, iWidth ); + + // compute gradient + icvGradientOfHistogram( piHistSmooth, piHistGrad ); + + // check for zeros + int iCntMaxima = 0; + for ( int i=iNumBins-2; (i>2) && (iCntMaxima<20); i--) + { + if ( (piHistGrad[i-1] < 0) && (piHistGrad[i] > 0) ) + { + piMaxPos[iCntMaxima] = i; + iCntMaxima++; + } + } + + iIdx = 0; + int iSumAroundMax = 0; + for ( int i=0; i= 3 + { + // CHECKING THRESHOLD FOR WHITE + int iIdxAccSum = 0, iAccum = 0; + for (int i=iNumBins-1; i>0; i--) + { + iAccum += piHistIntensity[i]; + // iMaxPix/18 is about 5,5%, minimum required number of pixels required for white part of chessboard + if ( iAccum > (iMaxPix/18) ) + { + iIdxAccSum = i; + break; + } + } + + int iIdxBGMax = 0; + int iBrightMax = piMaxPos[0]; + // printf("iBrightMax = %d\n", iBrightMax); + for ( int n=0; n= 250 && iIdxBGMax < iCntMaxima ) + { + iIdxBGMax++; + iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]]; + } + + for ( int n=iIdxBGMax + 1; n= iMaxVal ) + { + iMaxVal = piHistIntensity[piMaxPos[n]]; + iIdxBGMax = n; + } + } + + //SETTING THRESHOLD FOR BINARIZATION + int iDist2 = (iBrightMax - piMaxPos[iIdxBGMax])/2; + iThresh = iBrightMax - iDist2; + PRINTF("THRESHOLD SELECTED = %d, BRIGHTMAX = %d, DARKMAX = %d\n", iThresh, iBrightMax, piMaxPos[iIdxBGMax]); + } + + + if ( iThresh > 0 ) + { + for ( int jj=0; jj storage; CvMat stub, *img = (CvMat*)arr; + cImgSeg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1 ); + memcpy( cImgSeg->imageData, cvPtr1D( img, 0), img->rows*img->cols ); + + CvMat stub2, *thresh_img_new; + thresh_img_new = cvGetMat( cImgSeg, &stub2, 0, 0 ); int expected_corners_num = (pattern_size.width/2+1)*(pattern_size.height/2+1); @@ -255,7 +468,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, if( out_corner_count ) *out_corner_count = 0; - IplImage _img; int quad_count = 0, group_idx = 0, dilations = 0; img = cvGetMat( img, &stub ); @@ -300,209 +512,303 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, if( flags & CV_CALIB_CB_FAST_CHECK) { - cvGetImage(img, &_img); - int check_chessboard_result = cvCheckChessboard(&_img, pattern_size); - if(check_chessboard_result <= 0) + //perform new method for checking chessboard using a binary image. + //image is binarised using a threshold dependent on the image histogram + icvBinarizationHistogramBased( (unsigned char*) cImgSeg->imageData, cImgSeg->width, cImgSeg->height ); + check_chessboard_result = cvCheckChessboardBinary(cImgSeg, pattern_size); + if(check_chessboard_result <= 0) //fall back to the old method { - return 0; + IplImage _img; + cvGetImage(img, &_img); + check_chessboard_result = cvCheckChessboard(&_img, pattern_size); + if(check_chessboard_result <= 0) + { + return 0; + } } } + // empiric threshold level + // thresholding performed here and not inside the cycle to save processing time + int thresh_level; + if ( !(flags & CV_CALIB_CB_ADAPTIVE_THRESH) ) + { + double mean = cvAvg( img ).val[0]; + thresh_level = cvRound( mean - 10 ); + thresh_level = MAX( thresh_level, 10 ); + cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY ); + } // Try our standard "1" dilation, but if the pattern is not found, iterate the whole procedure with higher dilations. // This is necessary because some squares simply do not separate properly with a single dilation. However, // we want to use the minimum number of dilations possible since dilations cause the squares to become smaller, // making it difficult to detect smaller squares. - for( k = 0; k < 6; k++ ) + for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) { + if (found) + break; // already found it + + cvFree(&quads); + cvFree(&corners); + + //USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD + cvDilate( thresh_img_new, thresh_img_new, 0, 1 ); + + // So we can find rectangles that go to the edge, we draw a white line around the image edge. + // Otherwise FindContours will miss those clipped rectangle contours. + // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... + cvRectangle( thresh_img_new, cvPoint(0,0), cvPoint(thresh_img_new->cols-1, thresh_img_new->rows-1), CV_RGB(255,255,255), 3, 8); + quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img_new, flags, &max_quad_buf_size ); + PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); + + if( quad_count <= 0 ) + { + continue; + } + + // Find quad's neighbors + icvFindQuadNeighbors( quads, quad_count ); + + // allocate extra for adding in icvOrderFoundQuads + cvFree(&quad_group); + cvFree(&corner_group); + quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); + corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); + + for( group_idx = 0; ; group_idx++ ) + { + int count = 0; + count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); + + int icount = count; + if( count == 0 ) + break; + + // order the quad corners globally + // maybe delete or add some + PRINTF("Starting ordering of inner quads\n"); + count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, + pattern_size, storage ); + PRINTF("Orig count: %d After ordering: %d\n", icount, count); + + if (count == 0) + continue; // haven't found inner quads + + // If count is more than it should be, this will remove those quads + // which cause maximum deviation from a nice square pattern. + count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); + PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count); + + count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); + PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count); + + int n = count > 0 ? pattern_size.width * pattern_size.height : -count; + n = MIN( n, pattern_size.width * pattern_size.height ); + float sum_dist = 0; + int total = 0; + + for(int i = 0; i < n; i++ ) + { + int ni = 0; + float avgi = corner_group[i]->meanDist(&ni); + sum_dist += avgi*ni; + total += ni; + } + prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); + + if( count > 0 || (out_corner_count && -count > *out_corner_count) ) + { + // copy corners to output array + for(int i = 0; i < n; i++ ) + out_corners[i] = corner_group[i]->pt; + + if( out_corner_count ) + *out_corner_count = n; + + if( count == pattern_size.width*pattern_size.height && + icvCheckBoardMonotony( out_corners, pattern_size )) + { + found = 1; + break; + } + } + } + }//dilations + + // revert to old, slower, method if detection failed + if (!found) + { + for( k = 0; k < 6; k++ ) + { int max_quad_buf_size = 0; for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) { - if (found) - break; // already found it + if (found) + break; // already found it - cvFree(&quads); - cvFree(&corners); + cvFree(&quads); + cvFree(&corners); - /*if( k == 1 ) - { - //Pattern was not found using binarization - // Run multi-level quads extraction - // In case one-level binarization did not give enough number of quads - CV_CALL( quad_count = icvGenerateQuadsEx( &quads, &corners, storage, img, thresh_img, dilations, flags )); - PRINTF("EX quad count: %d/%d\n", quad_count, expected_corners_num); - } - else*/ - { - // convert the input grayscale image to binary (black-n-white) - if( flags & CV_CALIB_CB_ADAPTIVE_THRESH ) - { - int block_size = cvRound(prev_sqr_size == 0 ? - MIN(img->cols,img->rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1; + // convert the input grayscale image to binary (black-n-white) + if( flags & CV_CALIB_CB_ADAPTIVE_THRESH ) + { + int block_size = cvRound(prev_sqr_size == 0 ? + MIN(img->cols,img->rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1; - // convert to binary - cvAdaptiveThreshold( img, thresh_img, 255, - CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 ); - if (dilations > 0) - cvDilate( thresh_img, thresh_img, 0, dilations-1 ); - } - else - { - // Make dilation before the thresholding. - // It splits chessboard corners - //cvDilate( img, thresh_img, 0, 1 ); - - // empiric threshold level - double mean = cvAvg( img ).val[0]; - int thresh_level = cvRound( mean - 10 ); - thresh_level = MAX( thresh_level, 10 ); - - cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY ); - cvDilate( thresh_img, thresh_img, 0, dilations ); - } + // convert to binary + cvAdaptiveThreshold( img, thresh_img, 255, + CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 ); + if (dilations > 0) + cvDilate( thresh_img, thresh_img, 0, dilations-1 ); + } + //if flag CV_CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense + //to iterate over k + else + { + k = 6; + cvDilate( thresh_img, thresh_img, 0, 1 ); + } #ifdef DEBUG_CHESSBOARD - cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR); + cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR); #endif - // So we can find rectangles that go to the edge, we draw a white line around the image edge. - // Otherwise FindContours will miss those clipped rectangle contours. - // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... - cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1, - thresh_img->rows-1), CV_RGB(255,255,255), 3, 8); + // So we can find rectangles that go to the edge, we draw a white line around the image edge. + // Otherwise FindContours will miss those clipped rectangle contours. + // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... + cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1, + thresh_img->rows-1), CV_RGB(255,255,255), 3, 8); - quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); + quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); + PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); - PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); - } +#ifdef DEBUG_CHESSBOARD + cvCopy(dbg_img, dbg1_img); + cvNamedWindow("all_quads", 1); + // copy corners to temp array + for(int i = 0; i < quad_count; i++ ) + { + for (int z=0; z<4; z++) + { + CvPoint2D32f pt1, pt2; + CvScalar color = CV_RGB(30,255,30); + pt1 = quads[i].corners[z]->pt; + pt2 = quads[i].corners[(z+1)%4]->pt; + pt2.x = (pt1.x + pt2.x)/2; + pt2.y = (pt1.y + pt2.y)/2; + if (z>0) + color = CV_RGB(200,200,0); + cvLine( dbg1_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); + } + } + + + cvShowImage("all_quads", (IplImage*)dbg1_img); + cvWaitKey(); +#endif + + if( quad_count <= 0 ) + { + continue; + } + + // Find quad's neighbors + icvFindQuadNeighbors( quads, quad_count ); + + // allocate extra for adding in icvOrderFoundQuads + cvFree(&quad_group); + cvFree(&corner_group); + quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); + corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); + + for( group_idx = 0; ; group_idx++ ) + { + int count = 0; + count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); + + int icount = count; + if( count == 0 ) + break; + + // order the quad corners globally + // maybe delete or add some + PRINTF("Starting ordering of inner quads\n"); + count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage ); + + PRINTF("Orig count: %d After ordering: %d\n", icount, count); #ifdef DEBUG_CHESSBOARD - cvCopy(dbg_img, dbg1_img); - cvNamedWindow("all_quads", 1); - // copy corners to temp array - for(int i = 0; i < quad_count; i++ ) - { - for (int k=0; k<4; k++) - { - CvPoint2D32f pt1, pt2; - CvScalar color = CV_RGB(30,255,30); - pt1 = quads[i].corners[k]->pt; - pt2 = quads[i].corners[(k+1)%4]->pt; - pt2.x = (pt1.x + pt2.x)/2; - pt2.y = (pt1.y + pt2.y)/2; - if (k>0) - color = CV_RGB(200,200,0); - cvLine( dbg1_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); - } - } - - - cvShowImage("all_quads", (IplImage*)dbg1_img); - cvWaitKey(); + cvCopy(dbg_img,dbg2_img); + cvNamedWindow("connected_group", 1); + // copy corners to temp array + for(int i = 0; i < quad_count; i++ ) + { + if (quads[i].group_idx == group_idx) + for (int z=0; z<4; z++) + { + CvPoint2D32f pt1, pt2; + CvScalar color = CV_RGB(30,255,30); + if (quads[i].ordered) + color = CV_RGB(255,30,30); + pt1 = quads[i].corners[z]->pt; + pt2 = quads[i].corners[(z+1)%4]->pt; + pt2.x = (pt1.x + pt2.x)/2; + pt2.y = (pt1.y + pt2.y)/2; + if (z>0) + color = CV_RGB(200,200,0); + cvLine( dbg2_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); + } + } + cvShowImage("connected_group", (IplImage*)dbg2_img); + cvWaitKey(); #endif - if( quad_count <= 0 ) - continue; + if (count == 0) + continue; // haven't found inner quads - // Find quad's neighbors - icvFindQuadNeighbors( quads, quad_count ); - // allocate extra for adding in icvOrderFoundQuads - cvFree(&quad_group); - cvFree(&corner_group); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); + // If count is more than it should be, this will remove those quads + // which cause maximum deviation from a nice square pattern. + count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); + PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count); - for( group_idx = 0; ; group_idx++ ) + count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); + PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count); + + int n = count > 0 ? pattern_size.width * pattern_size.height : -count; + n = MIN( n, pattern_size.width * pattern_size.height ); + float sum_dist = 0; + int total = 0; + + for(int i = 0; i < n; i++ ) { - int count = 0; - count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage ); - - int icount = count; - if( count == 0 ) - break; - - // order the quad corners globally - // maybe delete or add some - PRINTF("Starting ordering of inner quads\n"); - count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, - pattern_size, max_quad_buf_size, storage ); - PRINTF("Orig count: %d After ordering: %d\n", icount, count); - - -#ifdef DEBUG_CHESSBOARD - cvCopy(dbg_img,dbg2_img); - cvNamedWindow("connected_group", 1); - // copy corners to temp array - for(int i = 0; i < quad_count; i++ ) - { - if (quads[i].group_idx == group_idx) - for (int k=0; k<4; k++) - { - CvPoint2D32f pt1, pt2; - CvScalar color = CV_RGB(30,255,30); - if (quads[i].ordered) - color = CV_RGB(255,30,30); - pt1 = quads[i].corners[k]->pt; - pt2 = quads[i].corners[(k+1)%4]->pt; - pt2.x = (pt1.x + pt2.x)/2; - pt2.y = (pt1.y + pt2.y)/2; - if (k>0) - color = CV_RGB(200,200,0); - cvLine( dbg2_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); - } - } - cvShowImage("connected_group", (IplImage*)dbg2_img); - cvWaitKey(); -#endif - - if (count == 0) - continue; // haven't found inner quads - - - // If count is more than it should be, this will remove those quads - // which cause maximum deviation from a nice square pattern. - count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size ); - PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count); - - count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size ); - PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count); - - { - int n = count > 0 ? pattern_size.width * pattern_size.height : -count; - n = MIN( n, pattern_size.width * pattern_size.height ); - float sum_dist = 0; - int total = 0; - - for(int i = 0; i < n; i++ ) - { - int ni = 0; - float avgi = corner_group[i]->meanDist(&ni); - sum_dist += avgi*ni; - total += ni; - } - prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); - - if( count > 0 || (out_corner_count && -count > *out_corner_count) ) - { - // copy corners to output array - for(int i = 0; i < n; i++ ) - out_corners[i] = corner_group[i]->pt; - - if( out_corner_count ) - *out_corner_count = n; - - if( count == pattern_size.width*pattern_size.height && - icvCheckBoardMonotony( out_corners, pattern_size )) - { - found = 1; - break; - } - } - } + int ni = 0; + float avgi = corner_group[i]->meanDist(&ni); + sum_dist += avgi*ni; + total += ni; } + prev_sqr_size = cvRound(sum_dist/MAX(total, 1)); + + if( count > 0 || (out_corner_count && -count > *out_corner_count) ) + { + // copy corners to output array + for(int i = 0; i < n; i++ ) + out_corners[i] = corner_group[i]->pt; + + if( out_corner_count ) + *out_corner_count = n; + + if( count == pattern_size.width*pattern_size.height && icvCheckBoardMonotony( out_corners, pattern_size )) + { + found = 1; + break; + } + } + } }//dilations - }// + }// for k = 0 -> 6 + } + if( found ) found = icvCheckBoardMonotony( out_corners, pattern_size ); @@ -559,6 +865,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvFree(&corners); cvFree(&quad_group); cvFree(&corner_group); + cvFree(&cImgSeg); throw; } @@ -566,6 +873,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvFree(&corners); cvFree(&quad_group); cvFree(&corner_group); + cvFree(&cImgSeg); return found; } diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib3d/src/checkchessboard.cpp index 715fe73ef8..5ecd37faab 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib3d/src/checkchessboard.cpp @@ -59,8 +59,8 @@ static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector >& quads, int class_id) { - const float min_aspect_ratio = 0.3f; - const float max_aspect_ratio = 3.0f; + const float min_aspect_ratio = 0.2f; + const float max_aspect_ratio = 5.0f; const float min_box_size = 10.0f; for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next) @@ -205,3 +205,97 @@ int cvCheckChessboard(IplImage* src, CvSize size) return result; } + +// does a fast check if a chessboard is in the input image. This is a workaround to +// a problem of cvFindChessboardCorners being slow on images with no chessboard +// - src: input binary image +// - size: chessboard size +// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, +// 0 if there is no chessboard, -1 in case of error +int cvCheckChessboardBinary(IplImage* src, CvSize size) +{ + if(src->nChannels > 1) + { + cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only", + __FILE__, __LINE__); + } + + if(src->depth != 8) + { + cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only", + __FILE__, __LINE__); + } + + CvMemStorage* storage = cvCreateMemStorage(); + + IplImage* white = cvCloneImage(src); + IplImage* black = cvCloneImage(src); + IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1); + + int result = 0; + + for ( int erosion_count = 0; erosion_count <= 3; erosion_count++ ) + { + if ( 1 == result ) + break; + + if ( 0 != erosion_count ) // first iteration keeps original images + { + cvErode(white, white, NULL, 1); + cvDilate(black, black, NULL, 1); + } + + cvThreshold(white, thresh, 128, 255, CV_THRESH_BINARY); + + CvSeq* first = 0; + std::vector > quads; + cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); + icvGetQuadrangleHypotheses(first, quads, 1); + + cvThreshold(black, thresh, 128, 255, CV_THRESH_BINARY_INV); + cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP); + icvGetQuadrangleHypotheses(first, quads, 0); + + const size_t min_quads_count = size.width*size.height/2; + std::sort(quads.begin(), quads.end(), less_pred); + + // now check if there are many hypotheses with similar sizes + // do this by floodfill-style algorithm + const float size_rel_dev = 0.4f; + + for(size_t i = 0; i < quads.size(); i++) + { + size_t j = i + 1; + for(; j < quads.size(); j++) + { + if(quads[j].first/quads[i].first > 1.0f + size_rel_dev) + { + break; + } + } + + if(j + 1 > min_quads_count + i) + { + // check the number of black and white squares + std::vector counts; + countClasses(quads, i, j, counts); + const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0)); + const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0)); + if(counts[0] < black_count*0.75 || + counts[1] < white_count*0.75) + { + continue; + } + result = 1; + break; + } + } + } + + cvReleaseImage(&thresh); + cvReleaseImage(&white); + cvReleaseImage(&black); + cvReleaseMemStorage(&storage); + + return result; +} \ No newline at end of file From b2dd128ec5fc75d337307c9168e57a99ce40c2be Mon Sep 17 00:00:00 2001 From: Kerry Billingham Date: Sat, 26 Mar 2016 23:30:35 +0000 Subject: [PATCH 051/153] Creation of Maven POM project and documentation. This commit introduces a POM.xml file to allow the build of OpenCV and Java bundles using Maven. An additonal directory has been created 'platforms/maven' to contain the POM and scripts used during the build process. An additional Markdown file is included to give instructions on how to build with Maven. --- platforms/maven/README.md | 64 ++++++ platforms/maven/pom.xml | 263 ++++++++++++++++++++++ platforms/maven/scripts/deb_package_check | 42 ++++ platforms/maven/scripts/properties | 90 ++++++++ 4 files changed, 459 insertions(+) create mode 100644 platforms/maven/README.md create mode 100644 platforms/maven/pom.xml create mode 100755 platforms/maven/scripts/deb_package_check create mode 100755 platforms/maven/scripts/properties diff --git a/platforms/maven/README.md b/platforms/maven/README.md new file mode 100644 index 0000000000..54f151a309 --- /dev/null +++ b/platforms/maven/README.md @@ -0,0 +1,64 @@ +# Using Maven to build OpenCV + +This page describes the how to build OpenCV using [Apache Maven](http://maven.apache.org/index.html). The Maven build is simply a wrapper around the existing CMake process but has the additional aims of creating Java OSGi-compatible bundles with included native support and also allow the build to be carried out on RaspberryPi (ARM) architecture. There is nothing preventing using the POM on x86 Linux however. + +The following assumes building on Debian-based Linux platform. + +## Overview +The Maven build process aims to: + 1. Provide a simpler route to build OpenCV and Java bundles. + 2. Automatically check the required native dependencies. + 3. Make the Java libraries OSGi compatible. + 4. Include the native OpenCV native library inside the Java bundle. + 5. Allow the build to function on x86, x86_64 or amd architectures, Debian-based Linux platform. + +### Starting the build +#### Environment variables +**Applicability:** All processors. + + The following environment variables must be set otherwise the build will fail and halt: + + * `$JAVA_HOME` (the absolute path to the JDK root directory) + * `$ANT_HOME` (the absolute path to the Ant root directory) + +It is recommended that advantage is taken of multiple processor cores to reduce build time. This can be done by setting a MAKEFLAGS environment variable specifying the number of parallel builds e.g.: + + * `$MAKEFLAGS="-j8"` + +However if this flag is not set the build will NOT fail. On a RaspberryPi 2 typical build times are 5 hours with `-j1` (which is the default if `$MAKEFLAGS` is not specified) and a little over 2 hours with `-j4`. + +All of the above environment variables can be set on an ad-hoc basis using 'export'. +#### Build Directory +**Applicability:** All processors + +By default the following build directories are created. + +`/build` + +`/build/target` + +Under `build` are the standard OpenCV artifacts. Under `build/target` can be found the OSGi compatible Java bundle. When deploying the bundle into an OSGi framework e.g. [Apache Karaf](http://karaf.apache.org/), loading of the native library is automatically taken care of. The standard Java library as created by the CMake process is also available as specified in the existing OpenCV documentation. + +The Maven build is initiated from the directory contain the `pom.xml` file. +#### x86 or x86_64 Architecture: +Generally all that is required is the standard Maven command: + +`mvn clean install` + +One of the first things the build will do is check the required native dependencies. The Maven build indicates the status of the required dependencies and will fail at this point if any are missing. Install using the package manager e.g. aptitude or apt-get, and restart the build with the above command. + +Once the build succesfully completes the OSGi compatible artifacts are available as described above in 'Build Directory'. + +#### ARM 32-bit Architecture - Raspbian Distribution +Similar to the x86 architecture the native dependencies are first checked so install any that are missing, however at the time of writing there are no official `libtbb2` and `libtbb-dev` packages in Raspbian. Version 4.4.3 of Intel's Thread Building Blocks library are available [here](http://www.javatechnics.com/thread-building-blocks-tbb-4-4-3-for-raspbian) as a Raspbian-compatible Debian packages. + +**PLEASE NOTE THESE ARE NOT OFFICIAL RASPBIAN PACKAGES. INSTALL AT YOUR OWN RISK.** + +OpenCV is built using CMake and the Maven build process uses the the [cmake-maven plugin](https://github.com/cmake-maven-project/cmake-maven-project). The cmake-maven plugin by default downloads CMake at build time but unfortunately there is no binary for ARM architecture currently available. As a work around it is possible to use the native CMake (which is checked for availability in the above dependency checks). Assuming all native dependencies are available the build can be started with the following command: + +`mvn clean install -Duse.native.cmake=true` + +Upon a successful build the libraries will be available as described above in 'Build Directory'. + +#### cmake-mave-plugin 3.4.1-b2-SNAPSHOT +Should this plugin not be available in Maven central, the source can be found at my GitHub page [here](https://github.com/jtkb/cmake-maven-project), checkout the `raspberrypi` branch and install. On x86 it is a standard Maven build and install command. If building on Raspbian you also need to supply the `-Duse.native.cmake=true` command-line option. diff --git a/platforms/maven/pom.xml b/platforms/maven/pom.xml new file mode 100644 index 0000000000..8314ab9f58 --- /dev/null +++ b/platforms/maven/pom.xml @@ -0,0 +1,263 @@ + + 4.0.0 + opencv.org + opencv + bundle + 3.1.0 + OpenCV + + + License Agreement For Open Source Computer Vision Library (3-clause BSD License) + + + + http://opencv.org/ + + scm:git:https://github.com/Itseez/opencv.git + https://github.com/Itseez/opencv + + + + Kerry Billingham + contact (at) AvionicEngineers (d0t) c(0)m + Java Technics + www.javatechnics.com + + + + + junit + junit + 3.8.1 + test + + + + ../../build + libopencv_java${lib.version.string}.so + + + + ${repo.name} + ${repo.url} + + + + ../../build/target + ../../build/src + ../../build/src + + + org.apache.maven.plugins + maven-clean-plugin + 3.0.0 + + + + ${build.directory} + + + + + + com.github.maven-nar + nar-maven-plugin + 3.3.0 + true + + + nar-initiliase + validate + + nar-validate + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + get-opencv-version + generate-resources + + exec + + + bash + ${project.basedir}/scripts + + properties + ../../../modules/core/include/opencv2/core/version.hpp + ${build.directory} + build.properties + + + + + setup-environment + validate + + exec + + + bash + ${project.basedir}/scripts + + deb_package_check + build-essential + cmake + git + libgtk2.0-dev + pkg-config + libavcodec-dev + libavformat-dev + libswscale-dev + python-dev + python-numpy + libtbb2 + libtbb-dev + libjpeg-dev + libpng12-dev + libtiff5-dev + libjasper-dev + libdc1394-22-dev + ant + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + set-arch-properties + process-resources + + read-project-properties + + + + ${build.directory}/build.properties + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.4.1 + + + validate + enforce-os + + enforce + + + + + unix + This POM is written to function on UNIX family of OS. + More specifically it should be a Debian flavour of Linux. + + + + + + enforce-environment + + enforce + + + + + ANT_HOME + $ANT_HOME is not set. Build may fail. + + + JAVA_HOME + $JAVA_HOME is not set. Build WILL fail. + + + WARN + MAKEFLAGS + No MAKEFLAGS environment variable. Build may be slow. +To speed up the build you can try exporting MAKEFLAGS=-jX where X equals the number of parallel builds. + + + + + + process-resources + check-versions-match + + enforce + + + + + project.version + ${opencv.version} + The Maven POM version ${project.version} does not match the extracted OpenCV version ${opencv.version}. + + + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + * + ${nativelibrary.name};osname=linux;processor=${osgi.processor} + ${build.directory}/lib/${nativelibrary.name} + + ${build.directory}/manifest + true + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + 3.4.1-b2-SNAPSHOT + + + cmake-generate + + generate + + + ../.. + ../../build + Unix Makefiles + + + + + + + cmake-compile + + compile + + + ../../build + + + + + + + diff --git a/platforms/maven/scripts/deb_package_check b/platforms/maven/scripts/deb_package_check new file mode 100755 index 0000000000..504e758f03 --- /dev/null +++ b/platforms/maven/scripts/deb_package_check @@ -0,0 +1,42 @@ +#!/bin/bash +########################################################################################### +# +# This script checks for the required Debian packages are installed +# to build OpenCV. +# Commandline parameters: +# $@ - These are the names of the packages to check with 'dpkg' +# +# Returns: +# 0 - All packages installed (success) +# 1 - One or more packages missing (failure) +# +# Kerry Billingham +# 20 April 2016 +# +########################################################################################### +red=$'\e[1;31m' +green=$'\e[1;32m' +end=$'\e[0m' +check_message="Checking for 'dpkg'" +dpkg -? &>/dev/null +if [ $? -ne 0 ]; then + printf "%-80s%s\n" "${check_message}" "${red} MISSING.${end}" + exit 1 +else + printf "%-80s%s\n" "${check_message}" "${green} INSTALLED.${end}" +fi + +declare -i packageMissing=0 +packageArray=( "$@" ) +for package in ${packageArray[@]}; do + check_message="Checking for package ${package}" + dpkg -s ${package} &>/dev/null + if [ $? -ne 0 ]; then + printf "%-80s%s\n" "${check_message}" "${red} MISSING.${end}" + packageMissing=1 + else + printf "%-80s%s\n" "${check_message}" "${green} INSTALLED.${end}" + fi +done + +exit $packageMissing diff --git a/platforms/maven/scripts/properties b/platforms/maven/scripts/properties new file mode 100755 index 0000000000..a413c2a3ad --- /dev/null +++ b/platforms/maven/scripts/properties @@ -0,0 +1,90 @@ +#!/bin/bash +##################################################################### +# This script extracts several properties and then writes them to a +# to a file, 'build.properties'. These properties include: +# +# 1. OpenCV version. +# 2. OpenVC version as a string for use by Maven. +# 3. The CPU binary word size. +# 4. Architecture string. +# 4. OSGi compatible CPU architecture string. +# +# There is no need to execute this script directly as it will be +# called during the Maven build process. +# +# Command-line parameters: +# $1 - Absolute path to the file containing Open CV version +# $2 - The build directory and where the output file will be written +# $3 - The name of the output file to write to. +# +# Returns: +# 0 - Successfully written the properties file. +# 1 - Error occured such as build directory does not exist +# or OpenCV version could not be determined or an +# unexpected error. +# +# Kerry Billingham +# 20 April 2016 +# +##################################################################### + +majorHashDefine="#define CV_VERSION_MAJOR" +minorHashDefine="#define CV_VERSION_MINOR" +revisionHashDefine="#define CV_VERSION_REVISION" +statusHashDefine="#define CV_VERSION_STATUS" + +#Test build directory exists +if [ ! -n "$2" ] || [ ! -d $2 ];then + echo "Build directory not specified or does not exist!" + exit 1 +fi + +if [ -n "$1" ] && [ -e $1 ];then + minorVersion=$(grep "${minorHashDefine}" $1 | grep -o ".$") + majorVersion=$(grep "${majorHashDefine}" $1 | grep -o ".$") + revision=$(grep "${revisionHashDefine}" $1 | grep -o ".$") + + bits=$(getconf LONG_BIT) + architecture=$(arch) + osgiProcessor="Not Set" + + case ${architecture} in + x86*) + echo "This is x86 (32 | 64) bit" + case ${bits} in + 32) + osgiProcessor="x86" + ;; + 64) + osgiProcessor="x86_64" + ;; + *) + osgiProcessor="Unknown" + esac + ;; + arm*) + echo "This is ARM" + byteOrder=$(lscpu | grep -i "byte order") + shopt -s nocasematch + if [[ "${byteOrder}" == *little* ]]; then + osgiProcessor="arm_le" + elif [[ "${byteOrder}}" == *big* ]]; then + osgiProcessor="arm_be" + fi + shopt -u nocasematch + ;; + *) + echo "This is unknown architecture" + esac + + echo "The version number will be ${majorVersion}.${minorVersion}.${revision}" + echo "opencv.version=${majorVersion}.${minorVersion}.${revision}" > ${2}/${3} + echo "lib.version.string=${majorVersion}${minorVersion}${revision}" >> ${2}/${3} + echo "bits=${bits}" >> ${2}/${3} + echo "architecture=$(arch)" >> ${2}/${3} + echo "osgi.processor=${osgiProcessor}" >> ${2}/${3} + exit 0 +else + echo "Could not locate file $1 to determine versioning." + exit 1 +fi From 2a350b11ddbbf56814eb2b4616e5fbb69598ee21 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 13 Jul 2016 11:45:32 +0300 Subject: [PATCH 052/153] Fixed several merge issues --- .../include/opencv2/calib3d/calib3d.hpp | 9 ------ modules/calib3d/src/calibinit.cpp | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp index 517372edc5..b3da45edd5 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp @@ -46,12 +46,3 @@ #endif #include "opencv2/calib3d.hpp" -// Performs a fast check if a chessboard is in the input image. This is a workaround to -// a problem of cvFindChessboardCorners being slow on images with no chessboard. -// This method works using a binary image as input -// - src: input binary image -// - size: chessboard size -// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, -// 0 if there is no chessboard, -1 in case of error -CVAPI(int) cvCheckChessboardBinary(IplImage* src, CvSize size); - diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 0f4676da97..398be938fe 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -202,6 +202,8 @@ static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ); +int cvCheckChessboardBinary(IplImage* src, CvSize size); + /***************************************************************************************************/ //COMPUTE INTENSITY HISTOGRAM OF INPUT IMAGE static int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector& piHist ); @@ -515,7 +517,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, //perform new method for checking chessboard using a binary image. //image is binarised using a threshold dependent on the image histogram icvBinarizationHistogramBased( (unsigned char*) cImgSeg->imageData, cImgSeg->width, cImgSeg->height ); - check_chessboard_result = cvCheckChessboardBinary(cImgSeg, pattern_size); + int check_chessboard_result = cvCheckChessboardBinary(cImgSeg, pattern_size); if(check_chessboard_result <= 0) //fall back to the old method { IplImage _img; @@ -528,16 +530,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, } } - // empiric threshold level - // thresholding performed here and not inside the cycle to save processing time - int thresh_level; - if ( !(flags & CV_CALIB_CB_ADAPTIVE_THRESH) ) - { - double mean = cvAvg( img ).val[0]; - thresh_level = cvRound( mean - 10 ); - thresh_level = MAX( thresh_level, 10 ); - cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY ); - } // Try our standard "1" dilation, but if the pattern is not found, iterate the whole procedure with higher dilations. // This is necessary because some squares simply do not separate properly with a single dilation. However, // we want to use the minimum number of dilations possible since dilations cause the squares to become smaller, @@ -550,6 +542,8 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvFree(&quads); cvFree(&corners); + int max_quad_buf_size = 0; + //USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD cvDilate( thresh_img_new, thresh_img_new, 0, 1 ); @@ -586,8 +580,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // order the quad corners globally // maybe delete or add some PRINTF("Starting ordering of inner quads\n"); - count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, - pattern_size, storage ); + count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage ); PRINTF("Orig count: %d After ordering: %d\n", icount, count); if (count == 0) @@ -637,6 +630,16 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // revert to old, slower, method if detection failed if (!found) { + // empiric threshold level + // thresholding performed here and not inside the cycle to save processing time + int thresh_level; + if ( !(flags & CV_CALIB_CB_ADAPTIVE_THRESH) ) + { + double mean = cvAvg( img ).val[0]; + thresh_level = cvRound( mean - 10 ); + thresh_level = MAX( thresh_level, 10 ); + cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY ); + } for( k = 0; k < 6; k++ ) { int max_quad_buf_size = 0; @@ -669,7 +672,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, } #ifdef DEBUG_CHESSBOARD - cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR); + cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR); #endif // So we can find rectangles that go to the edge, we draw a white line around the image edge. From 8215d20dbf4a380dab75c397e39c9c3e59a75de8 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 13 Jul 2016 12:11:44 +0300 Subject: [PATCH 053/153] fixup! Fixed several merge issues --- modules/calib3d/src/checkchessboard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib3d/src/checkchessboard.cpp index 5ecd37faab..5f954617d3 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib3d/src/checkchessboard.cpp @@ -57,6 +57,8 @@ # endif #endif +int cvCheckChessboardBinary(IplImage* src, CvSize size); + static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector >& quads, int class_id) { const float min_aspect_ratio = 0.2f; From b000663a8807faff57867164d53be7630db6a218 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 13 Jul 2016 15:45:48 +0300 Subject: [PATCH 054/153] Cleanup --- modules/calib3d/src/calibinit.cpp | 164 ++++++------------------------ 1 file changed, 33 insertions(+), 131 deletions(-) diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 398be938fe..55fadcb4f0 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -79,14 +79,7 @@ //#define ENABLE_TRIM_COL_ROW //#define DEBUG_CHESSBOARD -#ifdef DEBUG_CHESSBOARD -# include "opencv2/opencv_modules.hpp" -# ifdef HAVE_OPENCV_HIGHGUI -# include "opencv2/highgui.hpp" -# else -# undef DEBUG_CHESSBOARD -# endif -#endif + #ifdef DEBUG_CHESSBOARD static int PRINTF( const char* fmt, ... ) { @@ -400,38 +393,6 @@ bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows return true; } -#if 0 -static void -icvCalcAffineTranf2D32f(CvPoint2D32f* pts1, CvPoint2D32f* pts2, int count, CvMat* affine_trans) -{ - int i, j; - int real_count = 0; - for( j = 0; j < count; j++ ) - { - if( pts1[j].x >= 0 ) real_count++; - } - if(real_count < 3) return; - cv::Ptr xy = cvCreateMat( 2*real_count, 6, CV_32FC1 ); - cv::Ptr uv = cvCreateMat( 2*real_count, 1, CV_32FC1 ); - //estimate affine transfromation - for( i = 0, j = 0; j < count; j++ ) - { - if( pts1[j].x >= 0 ) - { - CV_MAT_ELEM( *xy, float, i*2+1, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 0 ) = pts2[j].x; - CV_MAT_ELEM( *xy, float, i*2+1, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 1 ) = pts2[j].y; - CV_MAT_ELEM( *xy, float, i*2, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 5 ) = \ - CV_MAT_ELEM( *xy, float, i*2+1, 0 ) = CV_MAT_ELEM( *xy, float, i*2+1, 1 ) = CV_MAT_ELEM( *xy, float, i*2+1, 4 ) = 0; - CV_MAT_ELEM( *xy, float, i*2, 4 ) = CV_MAT_ELEM( *xy, float, i*2+1, 5 ) = 1; - CV_MAT_ELEM( *uv, float, i*2, 0 ) = pts1[j].x; - CV_MAT_ELEM( *uv, float, i*2+1, 0 ) = pts1[j].y; - i++; - } - } - - cvSolve( xy, uv, affine_trans, CV_SVD ); -} -#endif CV_IMPL int cvFindChessboardCorners( const void* arr, CvSize pattern_size, @@ -449,11 +410,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, const int min_dilations = 0; const int max_dilations = 7; cv::Ptr norm_img, thresh_img; -#ifdef DEBUG_CHESSBOARD - cv::Ptr dbg_img; - cv::Ptr dbg1_img; - cv::Ptr dbg2_img; -#endif cv::Ptr storage; CvMat stub, *img = (CvMat*)arr; @@ -487,12 +443,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, storage.reset(cvCreateMemStorage(0)); thresh_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); -#ifdef DEBUG_CHESSBOARD - dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 ); - dbg1_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 ); - dbg2_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 ); -#endif - if( CV_MAT_CN(img->type) != 1 || (flags & CV_CALIB_CB_NORMALIZE_IMAGE) ) { // equalize the input image histogram - @@ -627,9 +577,12 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, } }//dilations + PRINTF("Chessboard detection result 0: %d\n", found); + // revert to old, slower, method if detection failed if (!found) { + PRINTF("Fallback to old algorithm\n"); // empiric threshold level // thresholding performed here and not inside the cycle to save processing time int thresh_level; @@ -671,10 +624,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvDilate( thresh_img, thresh_img, 0, 1 ); } -#ifdef DEBUG_CHESSBOARD - cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR); -#endif - // So we can find rectangles that go to the edge, we draw a white line around the image edge. // Otherwise FindContours will miss those clipped rectangle contours. // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()... @@ -684,31 +633,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); -#ifdef DEBUG_CHESSBOARD - cvCopy(dbg_img, dbg1_img); - cvNamedWindow("all_quads", 1); - // copy corners to temp array - for(int i = 0; i < quad_count; i++ ) - { - for (int z=0; z<4; z++) - { - CvPoint2D32f pt1, pt2; - CvScalar color = CV_RGB(30,255,30); - pt1 = quads[i].corners[z]->pt; - pt2 = quads[i].corners[(z+1)%4]->pt; - pt2.x = (pt1.x + pt2.x)/2; - pt2.y = (pt1.y + pt2.y)/2; - if (z>0) - color = CV_RGB(200,200,0); - cvLine( dbg1_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); - } - } - - - cvShowImage("all_quads", (IplImage*)dbg1_img); - cvWaitKey(); -#endif - if( quad_count <= 0 ) { continue; @@ -739,33 +663,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, PRINTF("Orig count: %d After ordering: %d\n", icount, count); - -#ifdef DEBUG_CHESSBOARD - cvCopy(dbg_img,dbg2_img); - cvNamedWindow("connected_group", 1); - // copy corners to temp array - for(int i = 0; i < quad_count; i++ ) - { - if (quads[i].group_idx == group_idx) - for (int z=0; z<4; z++) - { - CvPoint2D32f pt1, pt2; - CvScalar color = CV_RGB(30,255,30); - if (quads[i].ordered) - color = CV_RGB(255,30,30); - pt1 = quads[i].corners[z]->pt; - pt2 = quads[i].corners[(z+1)%4]->pt; - pt2.x = (pt1.x + pt2.x)/2; - pt2.y = (pt1.y + pt2.y)/2; - if (z>0) - color = CV_RGB(200,200,0); - cvLine( dbg2_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8); - } - } - cvShowImage("connected_group", (IplImage*)dbg2_img); - cvWaitKey(); -#endif - if (count == 0) continue; // haven't found inner quads @@ -812,10 +709,13 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, }// for k = 0 -> 6 } + PRINTF("Chessboard detection result 1: %d\n", found); if( found ) found = icvCheckBoardMonotony( out_corners, pattern_size ); + PRINTF("Chessboard detection result 2: %d\n", found); + // check that none of the found corners is too close to the image boundary if( found ) { @@ -830,36 +730,38 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, found = k == pattern_size.width*pattern_size.height; } - if( found && pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 ) + PRINTF("Chessboard detection result 3: %d\n", found); + + if( found ) { + if ( pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 ) + { int last_row = (pattern_size.height-1)*pattern_size.width; double dy0 = out_corners[last_row].y - out_corners[0].y; if( dy0 < 0 ) { - int n = pattern_size.width*pattern_size.height; - for(int i = 0; i < n/2; i++ ) - { - CvPoint2D32f temp; - CV_SWAP(out_corners[i], out_corners[n-i-1], temp); - } + int n = pattern_size.width*pattern_size.height; + for(int i = 0; i < n/2; i++ ) + { + CvPoint2D32f temp; + CV_SWAP(out_corners[i], out_corners[n-i-1], temp); + } } - } - - if( found ) - { - cv::Ptr gray; - if( CV_MAT_CN(img->type) != 1 ) - { - gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1)); - cvCvtColor(img, gray, CV_BGR2GRAY); - } - else - { - gray.reset(cvCloneMat(img)); - } - int wsize = 2; - cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height, - cvSize(wsize, wsize), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1)); + } + cv::Ptr gray; + if( CV_MAT_CN(img->type) != 1 ) + { + gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1)); + cvCvtColor(img, gray, CV_BGR2GRAY); + } + else + { + gray.reset(cvCloneMat(img)); + } + int wsize = 2; + cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height, + cvSize(wsize, wsize), cvSize(-1,-1), + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1)); } } catch(...) From 3bfe76e24ccfb46d07bb8158f2adbc38220f28f7 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 13 Jul 2016 15:46:48 +0300 Subject: [PATCH 055/153] Ported PR #4187 to master --- modules/calib3d/test/test_chesscorners_timing.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index 61287ab671..570c125c2a 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -113,11 +113,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) if( img2.empty() ) { ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename.c_str() ); - if( max_idx == 1 ) - { - code = cvtest::TS::FAIL_MISSING_TEST_DATA; - goto _exit_; - } + code = cvtest::TS::FAIL_MISSING_TEST_DATA; continue; } From 95da5ec245db6d038c43550b10cbb2c4964f82cd Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 13 Jul 2016 16:03:47 +0300 Subject: [PATCH 056/153] Restored check chessboard parameters --- modules/calib3d/src/checkchessboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib3d/src/checkchessboard.cpp index 5f954617d3..88c6baf107 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib3d/src/checkchessboard.cpp @@ -61,8 +61,8 @@ int cvCheckChessboardBinary(IplImage* src, CvSize size); static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector >& quads, int class_id) { - const float min_aspect_ratio = 0.2f; - const float max_aspect_ratio = 5.0f; + const float min_aspect_ratio = 0.3f; + const float max_aspect_ratio = 3.0f; const float min_box_size = 10.0f; for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next) From 998c43ffea70b4ee46d8ec7233e044be6bbb847d Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 14 Jul 2016 14:50:04 +0300 Subject: [PATCH 057/153] videoio: ffmpeg: fix get_fps() implementation --- modules/videoio/src/cap_ffmpeg_impl.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 4a725bc20b..a0b9d402f6 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1135,11 +1135,7 @@ int CvCapture_FFMPEG::get_bitrate() const double CvCapture_FFMPEG::get_fps() const { -#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0) - double fps = r2d(ic->streams[video_stream]->avg_frame_rate); -#else double fps = r2d(ic->streams[video_stream]->r_frame_rate); -#endif #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0) if (fps < eps_zero) From ea911d34c60d3868debc9dc3a5dc1179d93d5baf Mon Sep 17 00:00:00 2001 From: thierry Date: Thu, 14 Jul 2016 14:46:05 +0200 Subject: [PATCH 058/153] remove 2-channel png encoder/decoder support --- modules/imgcodecs/src/grfmt_png.cpp | 18 ++++++------------ modules/imgcodecs/src/loadsave.cpp | 5 +++++ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index a7dae83488..c8ff2447f1 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -187,27 +187,22 @@ bool PngDecoder::readHeader() if( bit_depth <= 8 || bit_depth == 16 ) { - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); if( num_trans > 0 ) m_type = CV_8UC4; else m_type = CV_8UC3; break; + case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: m_type = CV_8UC4; break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - m_type = CV_8UC2; - break; default: - if( num_trans > 0 ) - m_type = CV_8UC2; - else - m_type = CV_8UC1; + m_type = CV_8UC1; } if( bit_depth == 16 ) m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); @@ -230,7 +225,7 @@ bool PngDecoder::readData( Mat& img ) volatile bool result = false; AutoBuffer _buffer(m_height); uchar** buffer = _buffer; - int color = img.channels() > 2; + int color = img.channels() > 1; if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height ) { @@ -247,7 +242,7 @@ bool PngDecoder::readData( Mat& img ) else if( !isBigEndian() ) png_set_swap( png_ptr ); - if(img.channels() != 4 && img.channels() != 2) + if(img.channels() < 4) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png @@ -272,7 +267,7 @@ bool PngDecoder::readData( Mat& img ) png_set_gray_1_2_4_to_8( png_ptr ); #endif - if( CV_MAT_CN(m_type) > 2 && color ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB @@ -413,7 +408,6 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16, channels == 1 ? PNG_COLOR_TYPE_GRAY : - channels == 2 ? PNG_COLOR_TYPE_GRAY_ALPHA : channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index e0080bd3b9..70a31c37a2 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -452,6 +452,8 @@ static bool imwrite_( const String& filename, const Mat& image, Mat temp; const Mat* pimage = ℑ + CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 ); + ImageEncoder encoder = findEncoder( filename ); if( !encoder ) CV_Error( CV_StsError, "could not find a writer for the specified extension" ); @@ -588,6 +590,9 @@ bool imencode( const String& ext, InputArray _image, { Mat image = _image.getMat(); + int channels = image.channels(); + CV_Assert( channels == 1 || channels == 3 || channels == 4 ); + ImageEncoder encoder = findEncoder( ext ); if( !encoder ) CV_Error( CV_StsError, "could not find encoder for the specified extension" ); From 3c2f7ecc973e4d6290b15c25fbbcaa196b245bd7 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Fri, 15 Jul 2016 08:04:18 +0900 Subject: [PATCH 059/153] speed up accumulate, accumulateSquare, accumulateProduct and accumulateWeighted using SIMD * use SSE and/or AVX based on configuration * revise the test to verify the implementation --- modules/imgproc/src/accum.cpp | 1364 +++++++++++++++++++++++++++++ modules/video/test/test_accum.cpp | 6 +- 2 files changed, 1367 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index c7cbc40f37..e1f1ce71e8 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -83,6 +83,1370 @@ struct AccW_SIMD } }; +#if CV_AVX +template <> +struct Acc_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + if (!mask) + { + len *= cn; + for ( ; x <= len - 8 ; x += 8) + { + __m256 v_src = _mm256_loadu_ps(src + x); + __m256 v_dst = _mm256_loadu_ps(dst + x); + v_dst = _mm256_add_ps(v_src, v_dst); + _mm256_storeu_ps(dst + x, v_dst); + } + } + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + if (!mask) + { + len *= cn; + for ( ; x <= len - 8 ; x += 8) + { + __m256 v_src = _mm256_loadu_ps(src + x); + __m256d v_src0 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src,0)); + __m256d v_src1 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src,1)); + __m256d v_dst0 = _mm256_loadu_pd(dst + x); + __m256d v_dst1 = _mm256_loadu_pd(dst + x + 4); + v_dst0 = _mm256_add_pd(v_src0, v_dst0); + v_dst1 = _mm256_add_pd(v_src1, v_dst1); + _mm256_storeu_pd(dst + x, v_dst0); + _mm256_storeu_pd(dst + x + 4, v_dst1); + } + } + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m256d v_src = _mm256_loadu_pd(src + x); + __m256d v_dst = _mm256_loadu_pd(dst + x); + + v_dst = _mm256_add_pd(v_dst, v_src); + _mm256_storeu_pd(dst + x, v_dst); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + if (!mask) + { + len *= cn; + for ( ; x <= len - 8 ; x += 8) + { + __m256 v_src = _mm256_loadu_ps(src + x); + __m256 v_dst = _mm256_loadu_ps(dst + x); + + v_src = _mm256_mul_ps(v_src, v_src); + v_dst = _mm256_add_ps(v_src, v_dst); + _mm256_storeu_ps(dst + x, v_dst); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + if (!mask) + { + len *= cn; + for ( ; x <= len - 8 ; x += 8) + { + __m256 v_src = _mm256_loadu_ps(src + x); + __m256d v_src0 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src,0)); + __m256d v_src1 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src,1)); + __m256d v_dst0 = _mm256_loadu_pd(dst + x); + __m256d v_dst1 = _mm256_loadu_pd(dst + x + 4); + + v_src0 = _mm256_mul_pd(v_src0, v_src0); + v_src1 = _mm256_mul_pd(v_src1, v_src1); + v_dst0 = _mm256_add_pd(v_src0, v_dst0); + v_dst1 = _mm256_add_pd(v_src1, v_dst1); + _mm256_storeu_pd(dst + x, v_dst0); + _mm256_storeu_pd(dst + x + 4, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m256d v_src = _mm256_loadu_pd(src + x); + __m256d v_dst = _mm256_loadu_pd(dst + x); + + v_src = _mm256_mul_pd(v_src, v_src); + v_dst = _mm256_add_pd(v_dst, v_src); + _mm256_storeu_pd(dst + x, v_dst); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const float * src1, const float * src2, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m256 v_src0 = _mm256_loadu_ps(src1 + x); + __m256 v_src1 = _mm256_loadu_ps(src2 + x); + __m256 v_dst = _mm256_loadu_ps(dst + x); + __m256 v_src = _mm256_mul_ps(v_src0, v_src1); + + v_dst = _mm256_add_ps(v_src, v_dst); + _mm256_storeu_ps(dst + x, v_dst); + } + } + + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const float * src1, const float * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m256 v_1src = _mm256_loadu_ps(src1 + x); + __m256 v_2src = _mm256_loadu_ps(src2 + x); + __m256d v_src00 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_1src,0)); + __m256d v_src01 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_1src,1)); + __m256d v_src10 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_2src,0)); + __m256d v_src11 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_2src,1)); + __m256d v_dst0 = _mm256_loadu_pd(dst + x); + __m256d v_dst1 = _mm256_loadu_pd(dst + x + 4); + + __m256d v_src0 = _mm256_mul_pd(v_src00, v_src10); + __m256d v_src1 = _mm256_mul_pd(v_src01, v_src11); + v_dst0 = _mm256_add_pd(v_src0, v_dst0); + v_dst1 = _mm256_add_pd(v_src1, v_dst1); + _mm256_storeu_pd(dst + x, v_dst0); + _mm256_storeu_pd(dst + x + 4, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const double * src1, const double * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m256d v_src0 = _mm256_loadu_pd(src1 + x); + __m256d v_src1 = _mm256_loadu_pd(src2 + x); + __m256d v_dst = _mm256_loadu_pd(dst + x); + + v_src0 = _mm256_mul_pd(v_src0, v_src1); + v_dst = _mm256_add_pd(v_dst, v_src0); + _mm256_storeu_pd(dst + x, v_dst); + } + } + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn, float alpha) const + { + int x = 0; + __m256 v_alpha = _mm256_set1_ps(alpha); + __m256 v_beta = _mm256_set1_ps(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 16; x += 16) + { + _mm256_storeu_ps(dst + x, _mm256_add_ps(_mm256_mul_ps(_mm256_loadu_ps(dst + x), v_beta), _mm256_mul_ps(_mm256_loadu_ps(src + x), v_alpha))); + _mm256_storeu_ps(dst + x + 8, _mm256_add_ps(_mm256_mul_ps(_mm256_loadu_ps(dst + x + 8), v_beta), _mm256_mul_ps(_mm256_loadu_ps(src + x + 8), v_alpha))); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m256d v_alpha = _mm256_set1_pd(alpha); + __m256d v_beta = _mm256_set1_pd(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 16; x += 16) + { + __m256 v_src0 = _mm256_loadu_ps(src + x); + __m256 v_src1 = _mm256_loadu_ps(src + x + 8); + __m256d v_src00 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src0,0)); + __m256d v_src01 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src0,1)); + __m256d v_src10 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src1,0)); + __m256d v_src11 = _mm256_cvtps_pd(_mm256_extractf128_ps(v_src1,1)); + + _mm256_storeu_pd(dst + x, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x), v_beta), _mm256_mul_pd(v_src00, v_alpha))); + _mm256_storeu_pd(dst + x + 4, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x + 4), v_beta), _mm256_mul_pd(v_src01, v_alpha))); + _mm256_storeu_pd(dst + x + 8, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x + 8), v_beta), _mm256_mul_pd(v_src10, v_alpha))); + _mm256_storeu_pd(dst + x + 12, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x + 12), v_beta), _mm256_mul_pd(v_src11, v_alpha))); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m256d v_alpha = _mm256_set1_pd(alpha); + __m256d v_beta = _mm256_set1_pd(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m256d v_src0 = _mm256_loadu_pd(src + x); + __m256d v_src1 = _mm256_loadu_pd(src + x + 4); + + _mm256_storeu_pd(dst + x, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x), v_beta), _mm256_mul_pd(v_src0, v_alpha))); + _mm256_storeu_pd(dst + x + 4, _mm256_add_pd(_mm256_mul_pd(_mm256_loadu_pd(dst + x + 4), v_beta), _mm256_mul_pd(v_src1, v_alpha))); + } + } + + return x; + } +}; +#elif CV_SSE2 +template <> +struct Acc_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_loadu_ps(src + x))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_loadu_ps(src + x + 4))); + } + } + + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128 v_src = _mm_loadu_ps(src + x); + __m128d v_src0 = _mm_cvtps_pd(v_src); + __m128d v_src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_src, v_src, _MM_SHUFFLE(1, 0, 3, 2))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128d v_src0 = _mm_loadu_pd(src + x); + __m128d v_src1 = _mm_loadu_pd(src + x + 2); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128 v_src0 = _mm_loadu_ps(src + x); + __m128 v_src1 = _mm_loadu_ps(src + x + 4); + v_src0 = _mm_mul_ps(v_src0, v_src0); + v_src1 = _mm_mul_ps(v_src1, v_src1); + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + } + } + + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128 v_src = _mm_loadu_ps(src + x); + __m128d v_src0 = _mm_cvtps_pd(v_src); + __m128d v_src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_src, v_src, _MM_SHUFFLE(1, 0, 3, 2))); + v_src0 = _mm_mul_pd(v_src0, v_src0); + v_src1 = _mm_mul_pd(v_src1, v_src1); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128d v_src0 = _mm_loadu_pd(src + x); + __m128d v_src1 = _mm_loadu_pd(src + x + 2); + v_src0 = _mm_mul_pd(v_src0, v_src0); + v_src1 = _mm_mul_pd(v_src1, v_src1); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const float * src1, const float * src2, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_mul_ps(_mm_loadu_ps(src1 + x), _mm_loadu_ps(src2 + x)))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_mul_ps(_mm_loadu_ps(src1 + x + 4), _mm_loadu_ps(src2 + x + 4)))); + } + } + + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const float * src1, const float * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128 v_1src = _mm_loadu_ps(src1 + x); + __m128 v_2src = _mm_loadu_ps(src2 + x); + + __m128d v_1src0 = _mm_cvtps_pd(v_1src); + __m128d v_1src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_1src, v_1src, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_2src0 = _mm_cvtps_pd(v_2src); + __m128d v_2src1 = _mm_cvtps_pd(_mm_shuffle_ps(v_2src, v_2src, _MM_SHUFFLE(0, 0, 3, 2))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + + v_dst0 = _mm_add_pd(v_dst0, _mm_mul_pd(v_1src0, v_2src0)); + v_dst1 = _mm_add_pd(v_dst1, _mm_mul_pd(v_1src1, v_2src1)); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const double * src1, const double * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128d v_src00 = _mm_loadu_pd(src1 + x); + __m128d v_src01 = _mm_loadu_pd(src1 + x + 2); + __m128d v_src10 = _mm_loadu_pd(src2 + x); + __m128d v_src11 = _mm_loadu_pd(src2 + x + 2); + __m128d v_src0 = _mm_mul_pd(v_src00, v_src10); + __m128d v_src1 = _mm_mul_pd(v_src01, v_src11); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + } + } + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const float * src, float * dst, const uchar * mask, int len, int cn, float alpha) const + { + int x = 0; + __m128 v_alpha = _mm_set1_ps(alpha); + __m128 v_beta = _mm_set1_ps(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(dst + x), v_beta), _mm_mul_ps(_mm_loadu_ps(src + x), v_alpha))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(dst + x + 4), v_beta), _mm_mul_ps(_mm_loadu_ps(src + x + 4), v_alpha))); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const float * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m128d v_alpha = _mm_set1_pd(alpha); + __m128d v_beta = _mm_set1_pd(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128 v_src0 = _mm_loadu_ps(src + x); + __m128 v_src1 = _mm_loadu_ps(src + x + 4); + __m128d v_src00 = _mm_cvtps_pd(v_src0); + __m128d v_src01 = _mm_cvtps_pd(_mm_shuffle_ps(v_src0, v_src0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src10 = _mm_cvtps_pd(v_src1); + __m128d v_src11 = _mm_cvtps_pd(_mm_shuffle_ps(v_src1, v_src1, _MM_SHUFFLE(0, 0, 3, 2))); + + _mm_storeu_pd(dst + x, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x), v_beta), _mm_mul_pd(v_src00, v_alpha))); + _mm_storeu_pd(dst + x + 2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 2), v_beta), _mm_mul_pd(v_src01, v_alpha))); + _mm_storeu_pd(dst + x + 4, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 4), v_beta), _mm_mul_pd(v_src10, v_alpha))); + _mm_storeu_pd(dst + x + 6, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 6), v_beta), _mm_mul_pd(v_src11, v_alpha))); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const double * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m128d v_alpha = _mm_set1_pd(alpha); + __m128d v_beta = _mm_set1_pd(1.0f - alpha); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 4; x += 4) + { + __m128d v_src0 = _mm_loadu_pd(src + x); + __m128d v_src1 = _mm_loadu_pd(src + x + 2); + + _mm_storeu_pd(dst + x, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x), v_beta), _mm_mul_pd(v_src0, v_alpha))); + _mm_storeu_pd(dst + x + 2, _mm_add_pd(_mm_mul_pd(_mm_loadu_pd(dst + x + 2), v_beta), _mm_mul_pd(v_src1, v_alpha))); + } + } + + return x; + } +}; +#endif + +#if CV_SSE2 +template <> +struct Acc_SIMD +{ + int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 16; x += 16) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + } + } + else if (cn == 1) + { + __m128i v_255 = _mm_set1_epi8(-1); + + for ( ; x <= len - 16; x += 16) + { + __m128i v_src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src + x)), _mm_xor_si128(v_255, _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)(mask + x)), v_0))); + __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + } + } + + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_src0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi16(v_src, v_0); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(v_src0))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(v_src1))); + } + } + + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const uchar * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 16; x += 16) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_int0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_int1 = _mm_unpackhi_epi8(v_src, v_0); + __m128i v_int00 = _mm_unpacklo_epi16(v_int0, v_0); + __m128i v_int01 = _mm_unpackhi_epi16(v_int0, v_0); + __m128i v_int10 = _mm_unpacklo_epi16(v_int1, v_0); + __m128i v_int11 = _mm_unpackhi_epi16(v_int1, v_0); + __m128d v_src0 = _mm_cvtepi32_pd(v_int00); + __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int00, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src2 = _mm_cvtepi32_pd(v_int01); + __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int01, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src4 = _mm_cvtepi32_pd(v_int10); + __m128d v_src5 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int10, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src6 = _mm_cvtepi32_pd(v_int11); + __m128d v_src7 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int11, _MM_SHUFFLE(0, 0, 3, 2))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + __m128d v_dst4 = _mm_loadu_pd(dst + x + 8); + __m128d v_dst5 = _mm_loadu_pd(dst + x + 10); + __m128d v_dst6 = _mm_loadu_pd(dst + x + 12); + __m128d v_dst7 = _mm_loadu_pd(dst + x + 14); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + v_dst4 = _mm_add_pd(v_dst4, v_src4); + v_dst5 = _mm_add_pd(v_dst5, v_src5); + v_dst6 = _mm_add_pd(v_dst6, v_src6); + v_dst7 = _mm_add_pd(v_dst7, v_src7); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + _mm_storeu_pd(dst + x + 8, v_dst4); + _mm_storeu_pd(dst + x + 10, v_dst5); + _mm_storeu_pd(dst + x + 12, v_dst6); + _mm_storeu_pd(dst + x + 14, v_dst7); + } + } + return x; + } +}; + +template <> +struct Acc_SIMD +{ + int operator() (const ushort * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); + __m128d v_src0 = _mm_cvtepi32_pd(v_int0); + __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src2 = _mm_cvtepi32_pd(v_int1); + __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 16; x += 16) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + v_src0 = _mm_mullo_epi16(v_src0, v_src0); + v_src1 = _mm_mullo_epi16(v_src1, v_src1); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + } + } + else if (cn == 1) + { + + __m128i v_255 = _mm_set1_epi8(-1); + for ( ; x <= len - 16; x += 16) + { + + __m128i v_src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src + x)), _mm_xor_si128(v_255, _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)(mask + x)), v_0))); + __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + v_src0 = _mm_mullo_epi16(v_src0, v_src0); + v_src1 = _mm_mullo_epi16(v_src1, v_src1); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)))); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)))); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)))); + } + } + + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_src0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi16(v_src, v_0); + v_src0 = _mm_mullo_epi16(v_src0, v_src0); + v_src1 = _mm_mullo_epi16(v_src1, v_src1); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), _mm_cvtepi32_ps(v_src0))); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), _mm_cvtepi32_ps(v_src1))); + } + } + + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const uchar * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadl_epi64((const __m128i*)(src + x)); + __m128i v_int = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_int0 = _mm_unpacklo_epi16(v_int, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_int, v_0); + __m128d v_src0 = _mm_cvtepi32_pd(v_int0); + __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src2 = _mm_cvtepi32_pd(v_int1); + __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + v_src0 = _mm_mul_pd(v_src0, v_src0); + v_src1 = _mm_mul_pd(v_src1, v_src1); + v_src2 = _mm_mul_pd(v_src2, v_src2); + v_src3 = _mm_mul_pd(v_src3, v_src3); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + return x; + } +}; + +template <> +struct AccSqr_SIMD +{ + int operator() (const ushort * src, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); + __m128d v_src0 = _mm_cvtepi32_pd(v_int0); + __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src2 = _mm_cvtepi32_pd(v_int1); + __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + v_src0 = _mm_mul_pd(v_src0, v_src0); + v_src1 = _mm_mul_pd(v_src1, v_src1); + v_src2 = _mm_mul_pd(v_src2, v_src2); + v_src3 = _mm_mul_pd(v_src3, v_src3); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const uchar * src1, const uchar * src2, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + if (!mask) + { + for ( ; x <= len - 16; x += 16) + { + __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); + + __m128i v_1src0 = _mm_unpacklo_epi8(v_1src, v_0); + __m128i v_1src1 = _mm_unpackhi_epi8(v_1src, v_0); + __m128i v_2src0 = _mm_unpacklo_epi8(v_2src, v_0); + __m128i v_2src1 = _mm_unpackhi_epi8(v_2src, v_0); + __m128i v_src0 = _mm_mullo_epi16(v_1src0, v_2src0); + __m128i v_src1 = _mm_mullo_epi16(v_1src1, v_2src1); + __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); + __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); + __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); + __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src00)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src01)); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), v_src10)); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), v_src11)); + } + } + else if (cn == 1) + { + __m128i v_255 = _mm_set1_epi8(-1); + + for ( ; x <= len - 16; x += 16) + { + __m128i v_mask = _mm_loadu_si128((const __m128i*)(mask + x)); + v_mask = _mm_xor_si128(v_255, _mm_cmpeq_epi8(v_mask, v_0)); + __m128i v_1src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src1 + x)), v_mask); + __m128i v_2src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src2 + x)), v_mask); + + __m128i v_1src0 = _mm_unpacklo_epi8(v_1src, v_0); + __m128i v_1src1 = _mm_unpackhi_epi8(v_1src, v_0); + __m128i v_2src0 = _mm_unpacklo_epi8(v_2src, v_0); + __m128i v_2src1 = _mm_unpackhi_epi8(v_2src, v_0); + __m128i v_src0 = _mm_mullo_epi16(v_1src0, v_2src0); + __m128i v_src1 = _mm_mullo_epi16(v_1src1, v_2src1); + __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); + __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); + __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); + __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src00)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src01)); + _mm_storeu_ps(dst + x + 8, _mm_add_ps(_mm_loadu_ps(dst + x + 8), v_src10)); + _mm_storeu_ps(dst + x + 12, _mm_add_ps(_mm_loadu_ps(dst + x + 12), v_src11)); + } + } + + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const ushort * src1, const ushort * src2, float * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); + __m128 v_1src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_1src, v_0)); + __m128 v_1src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_1src, v_0)); + __m128 v_2src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_2src, v_0)); + __m128 v_2src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_2src, v_0)); + __m128 v_src0 = _mm_mul_ps(v_1src0, v_2src0); + __m128 v_src1 = _mm_mul_ps(v_1src1, v_2src1); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + } + } + else if (cn == 1) + { + __m128i v_65535 = _mm_set1_epi16(-1); + + for ( ; x <= len - 8; x += 8) + { + __m128i v_mask = _mm_loadl_epi64((const __m128i*)(mask + x)); + __m128i v_mask0 = _mm_unpacklo_epi8(v_mask, v_0); + v_mask0 = _mm_xor_si128(v_65535, _mm_cmpeq_epi16(v_mask0, v_0)); + + __m128i v_1src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src1 + x)), v_mask0); + __m128i v_2src = _mm_and_si128(_mm_loadu_si128((const __m128i*)(src2 + x)), v_mask0); + __m128 v_1src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_1src, v_0)); + __m128 v_1src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_1src, v_0)); + __m128 v_2src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_2src, v_0)); + __m128 v_2src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_2src, v_0)); + __m128 v_src0 = _mm_mul_ps(v_1src0, v_2src0); + __m128 v_src1 = _mm_mul_ps(v_1src1, v_2src1); + + _mm_storeu_ps(dst + x, _mm_add_ps(_mm_loadu_ps(dst + x), v_src0)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(_mm_loadu_ps(dst + x + 4), v_src1)); + } + } + + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const uchar * src1, const uchar * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_1src = _mm_loadl_epi64((const __m128i*)(src1 + x)); + __m128i v_2src = _mm_loadl_epi64((const __m128i*)(src2 + x)); + + __m128i v_1int = _mm_unpacklo_epi8(v_1src, v_0); + __m128i v_2int = _mm_unpacklo_epi8(v_2src, v_0); + __m128i v_1int0 = _mm_unpacklo_epi16(v_1int, v_0); + __m128i v_1int1 = _mm_unpackhi_epi16(v_1int, v_0); + __m128i v_2int0 = _mm_unpacklo_epi16(v_2int, v_0); + __m128i v_2int1 = _mm_unpackhi_epi16(v_2int, v_0); + __m128d v_src0 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int0),_mm_cvtepi32_pd(v_2int0)); + __m128d v_src1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int0, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int0, _MM_SHUFFLE(0, 0, 3, 2)))); + __m128d v_src2 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int1),_mm_cvtepi32_pd(v_2int1)); + __m128d v_src3 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int1, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int1, _MM_SHUFFLE(0, 0, 3, 2)))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + return x; + } +}; + +template <> +struct AccProd_SIMD +{ + int operator() (const ushort * src1, const ushort * src2, double * dst, const uchar * mask, int len, int cn) const + { + int x = 0; + + if (!mask) + { + __m128i v_0 = _mm_setzero_si128(); + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_1src = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i v_2src = _mm_loadu_si128((const __m128i*)(src2 + x)); + __m128i v_1int0 = _mm_unpacklo_epi16(v_1src, v_0); + __m128i v_1int1 = _mm_unpackhi_epi16(v_1src, v_0); + __m128i v_2int0 = _mm_unpacklo_epi16(v_2src, v_0); + __m128i v_2int1 = _mm_unpackhi_epi16(v_2src, v_0); + __m128d v_src0 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int0),_mm_cvtepi32_pd(v_2int0)); + __m128d v_src1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int0, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int0, _MM_SHUFFLE(0, 0, 3, 2)))); + __m128d v_src2 = _mm_mul_pd(_mm_cvtepi32_pd(v_1int1),_mm_cvtepi32_pd(v_2int1)); + __m128d v_src3 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_shuffle_epi32(v_1int1, _MM_SHUFFLE(0, 0, 3, 2))),_mm_cvtepi32_pd(_mm_shuffle_epi32(v_2int1, _MM_SHUFFLE(0, 0, 3, 2)))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(v_dst0, v_src0); + v_dst1 = _mm_add_pd(v_dst1, v_src1); + v_dst2 = _mm_add_pd(v_dst2, v_src2); + v_dst3 = _mm_add_pd(v_dst3, v_src3); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const uchar * src, float * dst, const uchar * mask, int len, int cn, float alpha) const + { + int x = 0; + __m128 v_alpha = _mm_set1_ps(alpha); + __m128 v_beta = _mm_set1_ps(1.0f - alpha); + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 16; x += 16) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_src0 = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_src1 = _mm_unpackhi_epi8(v_src, v_0); + __m128 v_src00 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src0, v_0)); + __m128 v_src01 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src0, v_0)); + __m128 v_src10 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src1, v_0)); + __m128 v_src11 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src1, v_0)); + + __m128 v_dst00 = _mm_loadu_ps(dst + x); + __m128 v_dst01 = _mm_loadu_ps(dst + x + 4); + __m128 v_dst10 = _mm_loadu_ps(dst + x + 8); + __m128 v_dst11 = _mm_loadu_ps(dst + x + 12); + + v_dst00 = _mm_add_ps(_mm_mul_ps(v_dst00, v_beta), _mm_mul_ps(v_src00, v_alpha)); + v_dst01 = _mm_add_ps(_mm_mul_ps(v_dst01, v_beta), _mm_mul_ps(v_src01, v_alpha)); + v_dst10 = _mm_add_ps(_mm_mul_ps(v_dst10, v_beta), _mm_mul_ps(v_src10, v_alpha)); + v_dst11 = _mm_add_ps(_mm_mul_ps(v_dst11, v_beta), _mm_mul_ps(v_src11, v_alpha)); + + _mm_storeu_ps(dst + x, v_dst00); + _mm_storeu_ps(dst + x + 4, v_dst01); + _mm_storeu_ps(dst + x + 8, v_dst10); + _mm_storeu_ps(dst + x + 12, v_dst11); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const ushort * src, float * dst, const uchar * mask, int len, int cn, float alpha) const + { + int x = 0; + __m128 v_alpha = _mm_set1_ps(alpha); + __m128 v_beta = _mm_set1_ps(1.0f - alpha); + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128 v_src0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src, v_0)); + __m128 v_src1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src, v_0)); + v_src0 = _mm_mul_ps(v_src0, v_alpha); + v_src1 = _mm_mul_ps(v_src1, v_alpha); + + __m128 v_dst0 = _mm_mul_ps(_mm_loadu_ps(dst + x), v_beta); + __m128 v_dst1 = _mm_mul_ps(_mm_loadu_ps(dst + x + 4), v_beta); + + _mm_storeu_ps(dst + x, _mm_add_ps(v_dst0, v_src0)); + _mm_storeu_ps(dst + x + 4, _mm_add_ps(v_dst1, v_src1)); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const uchar * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m128d v_alpha = _mm_set1_pd(alpha); + __m128d v_beta = _mm_set1_pd(1.0f - alpha); + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadl_epi64((const __m128i*)(src + x)); + __m128i v_int = _mm_unpacklo_epi8(v_src, v_0); + __m128i v_int0 = _mm_unpacklo_epi16(v_int, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_int, v_0); + __m128d v_src0 = _mm_cvtepi32_pd(v_int0); + __m128d v_src1 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src2 = _mm_cvtepi32_pd(v_int1); + __m128d v_src3 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + + __m128d v_dst0 = _mm_loadu_pd(dst + x); + __m128d v_dst1 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst2 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst3 = _mm_loadu_pd(dst + x + 6); + + v_dst0 = _mm_add_pd(_mm_mul_pd(v_dst0, v_beta), _mm_mul_pd(v_src0, v_alpha)); + v_dst1 = _mm_add_pd(_mm_mul_pd(v_dst1, v_beta), _mm_mul_pd(v_src1, v_alpha)); + v_dst2 = _mm_add_pd(_mm_mul_pd(v_dst2, v_beta), _mm_mul_pd(v_src2, v_alpha)); + v_dst3 = _mm_add_pd(_mm_mul_pd(v_dst3, v_beta), _mm_mul_pd(v_src3, v_alpha)); + + _mm_storeu_pd(dst + x, v_dst0); + _mm_storeu_pd(dst + x + 2, v_dst1); + _mm_storeu_pd(dst + x + 4, v_dst2); + _mm_storeu_pd(dst + x + 6, v_dst3); + } + } + + return x; + } +}; + +template <> +struct AccW_SIMD +{ + int operator() (const ushort * src, double * dst, const uchar * mask, int len, int cn, double alpha) const + { + int x = 0; + __m128d v_alpha = _mm_set1_pd(alpha); + __m128d v_beta = _mm_set1_pd(1.0f - alpha); + __m128i v_0 = _mm_setzero_si128(); + + if (!mask) + { + len *= cn; + for ( ; x <= len - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i v_int0 = _mm_unpacklo_epi16(v_src, v_0); + __m128i v_int1 = _mm_unpackhi_epi16(v_src, v_0); + __m128d v_src00 = _mm_cvtepi32_pd(v_int0); + __m128d v_src01 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int0, _MM_SHUFFLE(0, 0, 3, 2))); + __m128d v_src10 = _mm_cvtepi32_pd(v_int1); + __m128d v_src11 = _mm_cvtepi32_pd(_mm_shuffle_epi32(v_int1, _MM_SHUFFLE(0, 0, 3, 2))); + + __m128d v_dst00 = _mm_loadu_pd(dst + x); + __m128d v_dst01 = _mm_loadu_pd(dst + x + 2); + __m128d v_dst10 = _mm_loadu_pd(dst + x + 4); + __m128d v_dst11 = _mm_loadu_pd(dst + x + 6); + + v_dst00 = _mm_add_pd(_mm_mul_pd(v_dst00, v_beta), _mm_mul_pd(v_src00, v_alpha)); + v_dst01 = _mm_add_pd(_mm_mul_pd(v_dst01, v_beta), _mm_mul_pd(v_src01, v_alpha)); + v_dst10 = _mm_add_pd(_mm_mul_pd(v_dst10, v_beta), _mm_mul_pd(v_src10, v_alpha)); + v_dst11 = _mm_add_pd(_mm_mul_pd(v_dst11, v_beta), _mm_mul_pd(v_src11, v_alpha)); + + _mm_storeu_pd(dst + x, v_dst00); + _mm_storeu_pd(dst + x + 2, v_dst01); + _mm_storeu_pd(dst + x + 4, v_dst10); + _mm_storeu_pd(dst + x + 6, v_dst11); + } + } + + return x; + } +}; +#endif //CV_SSE2 + #if CV_NEON template <> diff --git a/modules/video/test/test_accum.cpp b/modules/video/test/test_accum.cpp index 6895bb4eae..fe045c6ea6 100644 --- a/modules/video/test/test_accum.cpp +++ b/modules/video/test/test_accum.cpp @@ -72,11 +72,11 @@ void CV_AccumBaseTest::get_test_array_types_and_sizes( int test_case_idx, vector >& sizes, vector >& types ) { RNG& rng = ts->get_rng(); - int depth = cvtest::randInt(rng) % 3, cn = cvtest::randInt(rng) & 1 ? 3 : 1; - int accdepth = std::max((int)(cvtest::randInt(rng) % 2 + 1), depth); + int depth = cvtest::randInt(rng) % 4, cn = cvtest::randInt(rng) & 1 ? 3 : 1; + int accdepth = (int)(cvtest::randInt(rng) % 2 + 1); int i, input_count = (int)test_array[INPUT].size(); cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); - depth = depth == 0 ? CV_8U : depth == 1 ? CV_32F : CV_64F; + depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_32F : CV_64F; accdepth = accdepth == 1 ? CV_32F : CV_64F; accdepth = MAX(accdepth, depth); From 3bf16da92d1cb42d429e9a81a3a0abd5cf3360a7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 15 Jul 2016 14:01:22 +0300 Subject: [PATCH 060/153] added condition for Qt5 --- modules/highgui/src/window_QT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 925bc222d4..ac2360260b 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -55,7 +55,7 @@ #endif #ifdef HAVE_QT_OPENGL - #ifdef Q_WS_X11 + #if defined Q_WS_X11 /* Qt4 */ || defined Q_OS_LINUX /* Qt5 */ #include #endif #endif From 957bf1452cc14e11fc74e204ae090e45f3c9b608 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 14 Jul 2016 17:13:09 +0300 Subject: [PATCH 061/153] added some tests for push_back --- modules/core/src/matrix.cpp | 4 ++-- modules/core/test/test_mat.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 08c5501e4e..02160ecd61 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -839,9 +839,9 @@ void Mat::push_back(const Mat& elems) bool eq = size == elems.size; size.p[0] = r; if( !eq ) - CV_Error(CV_StsUnmatchedSizes, ""); + CV_Error(CV_StsUnmatchedSizes, "Pushed vector length is not equal to matrix row length"); if( type() != elems.type() ) - CV_Error(CV_StsUnmatchedFormats, ""); + CV_Error(CV_StsUnmatchedFormats, "Pushed vector type is not the same as matrix type"); if( isSubmatrix() || dataend + step.p[0]*delta > datalimit ) reserve( std::max(r + delta, (r*3+1)/2) ); diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 9aeb02ed39..95e4c055d7 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1520,3 +1520,21 @@ TEST(Reduce, regression_should_fail_bug_4594) EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S)); EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S)); } + +TEST(Mat, push_back_vector) +{ + cv::Mat result(1, 5, CV_32FC1); + + std::vector vec1(result.cols + 1); + std::vector vec2(result.cols); + + EXPECT_THROW(result.push_back(vec1), cv::Exception); + EXPECT_THROW(result.push_back(vec2), cv::Exception); + + vec1.resize(result.cols); + + for (int i = 0; i < 5; ++i) + result.push_back(cv::Mat(vec1).reshape(1, 1)); + + ASSERT_EQ(6, result.rows); +} From 9f3b1f7e50cc6fd93ae9638e8039aa9265b2d853 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Fri, 15 Jul 2016 15:14:56 +0300 Subject: [PATCH 062/153] use HAVE_OPENGL instead of WITH_OPENGL for GPU opengl sample in this case the sample will not be built if OpenGL is not found --- samples/gpu/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/gpu/CMakeLists.txt b/samples/gpu/CMakeLists.txt index 852a8c2da8..8c97ea865a 100644 --- a/samples/gpu/CMakeLists.txt +++ b/samples/gpu/CMakeLists.txt @@ -81,9 +81,9 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) - if(NOT WITH_OPENGL) + if(NOT HAVE_OPENGL) list(REMOVE_ITEM all_samples "opengl.cpp") - endif(NOT WITH_OPENGL) + endif() foreach(sample_filename ${all_samples}) get_filename_component(sample ${sample_filename} NAME_WE) @@ -96,9 +96,9 @@ endif() if(INSTALL_C_EXAMPLES AND NOT WIN32) file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) - if(NOT WITH_OPENGL) + if(NOT HAVE_OPENGL) list(REMOVE_ITEM install_list "opengl.cpp") - endif(NOT WITH_OPENGL) + endif() install(FILES ${install_list} DESTINATION ${OPENCV_SAMPLES_SRC_INSTALL_PATH}/gpu PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) From 99b0845cd5945a86485ae3b6b51ea3020c6d60f5 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 13 Jul 2016 19:29:58 +0300 Subject: [PATCH 063/153] ffmpeg windows wrapper 2.7.1=>3.1.1, openh264 1.4.0=>1.5.0, vpx 1.5.0 --- 3rdparty/ffmpeg/ffmpeg.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/3rdparty/ffmpeg/ffmpeg.cmake b/3rdparty/ffmpeg/ffmpeg.cmake index 448ad2bb2c..000b713b02 100644 --- a/3rdparty/ffmpeg/ffmpeg.cmake +++ b/3rdparty/ffmpeg/ffmpeg.cmake @@ -1,9 +1,9 @@ -# Binary branch name: ffmpeg/master_20150703 -# Binaries were created for OpenCV: e379ea6ed60b0caad4d4e3eea096e9d850cb8c86 -set(FFMPEG_BINARIES_COMMIT "8aeefc4efe3215de89d8c7e114ae6f7a6091b8eb") -set(FFMPEG_FILE_HASH_BIN32 "89c783eee1c47bfc733f08334ec2e31c") -set(FFMPEG_FILE_HASH_BIN64 "35fe6ccdda6d7a04e9056b0d73b98e76") -set(FFMPEG_FILE_HASH_CMAKE "8606f947a780071f8fcce8cbf39ceef5") +# Binary branch name: ffmpeg/master_20160715 +# Binaries were created for OpenCV: 0e6aa189cb9a9642b0ae7983d301693516faad5d +set(FFMPEG_BINARIES_COMMIT "7eef9080d3271c7547d303fa839a62e1124ff1e6") +set(FFMPEG_FILE_HASH_BIN32 "3bb2a8388af90adf6c762210e696400d") +set(FFMPEG_FILE_HASH_BIN64 "ebcfc963f0a94f7e83d58d60eaf23849") +set(FFMPEG_FILE_HASH_CMAKE "f99941d10c1e87bf16b9055e8fc91ab2") set(FFMPEG_DOWNLOAD_URL ${OPENCV_FFMPEG_URL};$ENV{OPENCV_FFMPEG_URL};https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${FFMPEG_BINARIES_COMMIT}/ffmpeg/) From bd7c21d83e10096e279bee099d56f7fad2d2b431 Mon Sep 17 00:00:00 2001 From: Arthur Cinader Date: Fri, 15 Jul 2016 09:57:12 -0400 Subject: [PATCH 064/153] Fix explanation to refelect how matching currently works. --- .../template_matching/template_matching.markdown | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown index bdba55a799..464fd8de16 100644 --- a/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown +++ b/doc/tutorials/imgproc/histograms/template_matching/template_matching.markdown @@ -70,13 +70,12 @@ that should be used to find the match. - The mask must have the same dimensions as the template -- The mask should be a grayscale image where each pixel contains some value from black to white. - Pixels that are white are fully included in calculating the best match. Pixels that are black - are excluded from the match. A value between black and white will include some of - the match in proportion to how dark the pixel is. Although the image should be a grayscale whose - output from the file command should look something like: "PNG image data, 128 x 128, 8-bit gray - +alpha, non-interlaced", opencv will read the image into an rgb matrix that will be applied - during the image match. +- The mask should have a CV_8U or CV_32F depth and the same number of channels + as the template image. In CV_8U case, the mask values are treated as binary, + i.e. zero and non-zero. In CV_32F case, the values should fall into [0..1] + range and the template pixels will be multiplied by the corresponding mask pixel + values. Since the input images in the sample have the CV_8UC3 type, the mask + is also read as color image. ![](images/Template_Matching_Mask_Example.jpg) From 6f8695c1785dc021e4efba566932e90c9061aa50 Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sat, 16 Jul 2016 22:01:28 +0900 Subject: [PATCH 065/153] improve RowVec_8u32s(). --- modules/imgproc/src/filter.cpp | 46 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 13d02def88..721c3c5c2d 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -506,56 +506,52 @@ struct RowVec_8u32s if( smallValues ) { - for( ; i <= width - 16; i += 16 ) + __m128i z = _mm_setzero_si128(); + for( ; i <= width - 8; i += 8 ) { const uchar* src = _src + i; - __m128i f, z = _mm_setzero_si128(), s0 = z, s1 = z, s2 = z, s3 = z; - __m128i x0, x1, x2, x3; + __m128i s0 = z, s1 = z; for( k = 0; k < _ksize; k++, src += cn ) { - f = _mm_cvtsi32_si128(_kx[k]); + __m128i f = _mm_cvtsi32_si128(_kx[k]); f = _mm_shuffle_epi32(f, 0); - f = _mm_packs_epi32(f, f); - x0 = _mm_loadu_si128((const __m128i*)src); - x2 = _mm_unpackhi_epi8(x0, z); + __m128i x0 = _mm_loadl_epi64((const __m128i*)src); x0 = _mm_unpacklo_epi8(x0, z); - x1 = _mm_mulhi_epi16(x0, f); - x3 = _mm_mulhi_epi16(x2, f); - x0 = _mm_mullo_epi16(x0, f); - x2 = _mm_mullo_epi16(x2, f); - s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1)); - s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(x0, x1)); - s2 = _mm_add_epi32(s2, _mm_unpacklo_epi16(x2, x3)); - s3 = _mm_add_epi32(s3, _mm_unpackhi_epi16(x2, x3)); + __m128i x1 = _mm_unpackhi_epi16(x0, z); + x0 = _mm_unpacklo_epi16(x0, z); + + x0 = _mm_madd_epi16(x0, f); + x1 = _mm_madd_epi16(x1, f); + + s0 = _mm_add_epi32(s0, x0); + s1 = _mm_add_epi32(s1, x1); } _mm_store_si128((__m128i*)(dst + i), s0); _mm_store_si128((__m128i*)(dst + i + 4), s1); - _mm_store_si128((__m128i*)(dst + i + 8), s2); - _mm_store_si128((__m128i*)(dst + i + 12), s3); } - for( ; i <= width - 4; i += 4 ) + if( i <= width - 4 ) { const uchar* src = _src + i; - __m128i f, z = _mm_setzero_si128(), s0 = z, x0, x1; + __m128i s0 = z; for( k = 0; k < _ksize; k++, src += cn ) { - f = _mm_cvtsi32_si128(_kx[k]); + __m128i f = _mm_cvtsi32_si128(_kx[k]); f = _mm_shuffle_epi32(f, 0); - f = _mm_packs_epi32(f, f); - x0 = _mm_cvtsi32_si128(*(const int*)src); + __m128i x0 = _mm_cvtsi32_si128(*(const int*)src); x0 = _mm_unpacklo_epi8(x0, z); - x1 = _mm_mulhi_epi16(x0, f); - x0 = _mm_mullo_epi16(x0, f); - s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1)); + x0 = _mm_unpacklo_epi16(x0, z); + x0 = _mm_madd_epi16(x0, f); + s0 = _mm_add_epi32(s0, x0); } _mm_store_si128((__m128i*)(dst + i), s0); + i += 4; } } return i; From d9a56f6590a7942494d30f9dbc472e00a930a622 Mon Sep 17 00:00:00 2001 From: Philippe FOUBERT Date: Sun, 17 Jul 2016 12:22:37 +0200 Subject: [PATCH 066/153] Resolves issue #6931 --- modules/core/include/opencv2/core/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index a69d42fcb1..37eb1ea0a5 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -58,7 +58,7 @@ #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) -#define CVAUX_STRW_EXP(__A) L#__A +#define CVAUX_STRW_EXP(__A) L ## #__A #define CVAUX_STRW(__A) CVAUX_STRW_EXP(__A) #define CV_VERSION CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS From 7f64f31f662edf718363831b4a3a77e6500610c5 Mon Sep 17 00:00:00 2001 From: catree Date: Sun, 17 Jul 2016 23:21:15 +0200 Subject: [PATCH 067/153] Fix NAryMatIterator code example. --- modules/core/include/opencv2/core/mat.hpp | 26 +++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index a0560a197e..ab2ba79734 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -3146,21 +3146,29 @@ The example below illustrates how you can compute a normalized and threshold 3D } minProb *= image.rows*image.cols; - Mat plane; - NAryMatIterator it(&hist, &plane, 1); + + // initialize iterator (the style is different from STL). + // after initialization the iterator will contain + // the number of slices or planes the iterator will go through. + // it simultaneously increments iterators for several matrices + // supplied as a null terminated list of pointers + const Mat* arrays[] = {&hist, 0}; + Mat planes[1]; + NAryMatIterator itNAry(arrays, planes, 1); double s = 0; // iterate through the matrix. on each iteration - // it.planes[*] (of type Mat) will be set to the current plane. - for(int p = 0; p < it.nplanes; p++, ++it) + // itNAry.planes[i] (of type Mat) will be set to the current plane + // of the i-th n-dim matrix passed to the iterator constructor. + for(int p = 0; p < itNAry.nplanes; p++, ++itNAry) { - threshold(it.planes[0], it.planes[0], minProb, 0, THRESH_TOZERO); - s += sum(it.planes[0])[0]; + threshold(itNAry.planes[0], itNAry.planes[0], minProb, 0, THRESH_TOZERO); + s += sum(itNAry.planes[0])[0]; } s = 1./s; - it = NAryMatIterator(&hist, &plane, 1); - for(int p = 0; p < it.nplanes; p++, ++it) - it.planes[0] *= s; + itNAry = NAryMatIterator(arrays, planes, 1); + for(int p = 0; p < itNAry.nplanes; p++, ++itNAry) + itNAry.planes[0] *= s; } @endcode */ From a25dba001d2e09899d9b5e5c942ac28d6a1ffe6a Mon Sep 17 00:00:00 2001 From: k-shinotsuka Date: Sun, 17 Jul 2016 14:32:52 +0900 Subject: [PATCH 068/153] improve SymmRowSmallVec_8u32s(). --- modules/imgproc/src/filter.cpp | 238 +++++++++++++++------------------ 1 file changed, 106 insertions(+), 132 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 13d02def88..8c4a94c311 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -652,41 +652,30 @@ struct SymmRowSmallVec_8u32s { __m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0), k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0); - k0 = _mm_packs_epi32(k0, k0); k1 = _mm_packs_epi32(k1, k1); - for( ; i <= width - 16; i += 16, src += 16 ) + for( ; i <= width - 8; i += 8, src += 8 ) { - __m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3; - x0 = _mm_loadu_si128((__m128i*)(src - cn)); - x1 = _mm_loadu_si128((__m128i*)src); - x2 = _mm_loadu_si128((__m128i*)(src + cn)); - y0 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z)); - x0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z)); - y1 = _mm_unpackhi_epi8(x1, z); + __m128i x0 = _mm_loadl_epi64((__m128i*)(src - cn)); + __m128i x1 = _mm_loadl_epi64((__m128i*)src); + __m128i x2 = _mm_loadl_epi64((__m128i*)(src + cn)); + + x0 = _mm_unpacklo_epi8(x0, z); x1 = _mm_unpacklo_epi8(x1, z); + x2 = _mm_unpacklo_epi8(x2, z); + __m128i x3 = _mm_unpacklo_epi16(x0, x2); + __m128i x4 = _mm_unpackhi_epi16(x0, x2); + __m128i x5 = _mm_unpacklo_epi16(x1, z); + __m128i x6 = _mm_unpackhi_epi16(x1, z); + x3 = _mm_madd_epi16(x3, k1); + x4 = _mm_madd_epi16(x4, k1); + x5 = _mm_madd_epi16(x5, k0); + x6 = _mm_madd_epi16(x6, k0); + x3 = _mm_add_epi32(x3, x5); + x4 = _mm_add_epi32(x4, x6); - t1 = _mm_mulhi_epi16(x1, k0); - t0 = _mm_mullo_epi16(x1, k0); - x2 = _mm_mulhi_epi16(x0, k1); - x0 = _mm_mullo_epi16(x0, k1); - z0 = _mm_unpacklo_epi16(t0, t1); - z1 = _mm_unpackhi_epi16(t0, t1); - z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(x0, x2)); - z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(x0, x2)); - - t1 = _mm_mulhi_epi16(y1, k0); - t0 = _mm_mullo_epi16(y1, k0); - y1 = _mm_mulhi_epi16(y0, k1); - y0 = _mm_mullo_epi16(y0, k1); - z2 = _mm_unpacklo_epi16(t0, t1); - z3 = _mm_unpackhi_epi16(t0, t1); - z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1)); - z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1)); - _mm_store_si128((__m128i*)(dst + i), z0); - _mm_store_si128((__m128i*)(dst + i + 4), z1); - _mm_store_si128((__m128i*)(dst + i + 8), z2); - _mm_store_si128((__m128i*)(dst + i + 12), z3); + _mm_store_si128((__m128i*)(dst + i), x3); + _mm_store_si128((__m128i*)(dst + i + 4), x4); } } } @@ -717,57 +706,45 @@ struct SymmRowSmallVec_8u32s __m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0), k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0), k2 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[2]), 0); - k0 = _mm_packs_epi32(k0, k0); k1 = _mm_packs_epi32(k1, k1); k2 = _mm_packs_epi32(k2, k2); - for( ; i <= width - 16; i += 16, src += 16 ) + for( ; i <= width - 8; i += 8, src += 8 ) { - __m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3; - x0 = _mm_loadu_si128((__m128i*)(src - cn)); - x1 = _mm_loadu_si128((__m128i*)src); - x2 = _mm_loadu_si128((__m128i*)(src + cn)); - y0 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z)); - x0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z)); - y1 = _mm_unpackhi_epi8(x1, z); - x1 = _mm_unpacklo_epi8(x1, z); + __m128i x0 = _mm_loadl_epi64((__m128i*)src); - t1 = _mm_mulhi_epi16(x1, k0); - t0 = _mm_mullo_epi16(x1, k0); - x2 = _mm_mulhi_epi16(x0, k1); - x0 = _mm_mullo_epi16(x0, k1); - z0 = _mm_unpacklo_epi16(t0, t1); - z1 = _mm_unpackhi_epi16(t0, t1); - z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(x0, x2)); - z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(x0, x2)); + x0 = _mm_unpacklo_epi8(x0, z); + __m128i x1 = _mm_unpacklo_epi16(x0, z); + __m128i x2 = _mm_unpackhi_epi16(x0, z); + x1 = _mm_madd_epi16(x1, k0); + x2 = _mm_madd_epi16(x2, k0); - t1 = _mm_mulhi_epi16(y1, k0); - t0 = _mm_mullo_epi16(y1, k0); - y1 = _mm_mulhi_epi16(y0, k1); - y0 = _mm_mullo_epi16(y0, k1); - z2 = _mm_unpacklo_epi16(t0, t1); - z3 = _mm_unpackhi_epi16(t0, t1); - z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1)); - z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1)); + __m128i x3 = _mm_loadl_epi64((__m128i*)(src - cn)); + __m128i x4 = _mm_loadl_epi64((__m128i*)(src + cn)); - x0 = _mm_loadu_si128((__m128i*)(src - cn*2)); - x1 = _mm_loadu_si128((__m128i*)(src + cn*2)); - y1 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z)); - y0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z)); + x3 = _mm_unpacklo_epi8(x3, z); + x4 = _mm_unpacklo_epi8(x4, z); + __m128i x5 = _mm_unpacklo_epi16(x3, x4); + __m128i x6 = _mm_unpackhi_epi16(x3, x4); + x5 = _mm_madd_epi16(x5, k1); + x6 = _mm_madd_epi16(x6, k1); + x1 = _mm_add_epi32(x1, x5); + x2 = _mm_add_epi32(x2, x6); - t1 = _mm_mulhi_epi16(y0, k2); - t0 = _mm_mullo_epi16(y0, k2); - y0 = _mm_mullo_epi16(y1, k2); - y1 = _mm_mulhi_epi16(y1, k2); - z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(t0, t1)); - z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(t0, t1)); - z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1)); - z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1)); + x3 = _mm_loadl_epi64((__m128i*)(src - cn*2)); + x4 = _mm_loadl_epi64((__m128i*)(src + cn*2)); - _mm_store_si128((__m128i*)(dst + i), z0); - _mm_store_si128((__m128i*)(dst + i + 4), z1); - _mm_store_si128((__m128i*)(dst + i + 8), z2); - _mm_store_si128((__m128i*)(dst + i + 12), z3); + x3 = _mm_unpacklo_epi8(x3, z); + x4 = _mm_unpacklo_epi8(x4, z); + x5 = _mm_unpacklo_epi16(x3, x4); + x6 = _mm_unpackhi_epi16(x3, x4); + x5 = _mm_madd_epi16(x5, k2); + x6 = _mm_madd_epi16(x6, k2); + x1 = _mm_add_epi32(x1, x5); + x2 = _mm_add_epi32(x2, x6); + + _mm_store_si128((__m128i*)(dst + i), x1); + _mm_store_si128((__m128i*)(dst + i + 4), x2); } } } @@ -791,77 +768,75 @@ struct SymmRowSmallVec_8u32s } else { - __m128i k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0); - k1 = _mm_packs_epi32(k1, k1); + __m128i k0 = _mm_set_epi32(-kx[1], kx[1], -kx[1], kx[1]); + k0 = _mm_packs_epi32(k0, k0); for( ; i <= width - 16; i += 16, src += 16 ) { - __m128i x0, x1, y0, y1, z0, z1, z2, z3; - x0 = _mm_loadu_si128((__m128i*)(src + cn)); - x1 = _mm_loadu_si128((__m128i*)(src - cn)); - y0 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z)); - x0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z)); + __m128i x0 = _mm_loadu_si128((__m128i*)(src + cn)); + __m128i x1 = _mm_loadu_si128((__m128i*)(src - cn)); - x1 = _mm_mulhi_epi16(x0, k1); - x0 = _mm_mullo_epi16(x0, k1); - z0 = _mm_unpacklo_epi16(x0, x1); - z1 = _mm_unpackhi_epi16(x0, x1); + __m128i x2 = _mm_unpacklo_epi8(x0, z); + __m128i x3 = _mm_unpacklo_epi8(x1, z); + __m128i x4 = _mm_unpackhi_epi8(x0, z); + __m128i x5 = _mm_unpackhi_epi8(x1, z); + __m128i x6 = _mm_unpacklo_epi16(x2, x3); + __m128i x7 = _mm_unpacklo_epi16(x4, x5); + __m128i x8 = _mm_unpackhi_epi16(x2, x3); + __m128i x9 = _mm_unpackhi_epi16(x4, x5); + x6 = _mm_madd_epi16(x6, k0); + x7 = _mm_madd_epi16(x7, k0); + x8 = _mm_madd_epi16(x8, k0); + x9 = _mm_madd_epi16(x9, k0); - y1 = _mm_mulhi_epi16(y0, k1); - y0 = _mm_mullo_epi16(y0, k1); - z2 = _mm_unpacklo_epi16(y0, y1); - z3 = _mm_unpackhi_epi16(y0, y1); - _mm_store_si128((__m128i*)(dst + i), z0); - _mm_store_si128((__m128i*)(dst + i + 4), z1); - _mm_store_si128((__m128i*)(dst + i + 8), z2); - _mm_store_si128((__m128i*)(dst + i + 12), z3); + _mm_store_si128((__m128i*)(dst + i), x6); + _mm_store_si128((__m128i*)(dst + i + 4), x8); + _mm_store_si128((__m128i*)(dst + i + 8), x7); + _mm_store_si128((__m128i*)(dst + i + 12), x9); } } } else if( _ksize == 5 ) { - __m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0), - k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0), - k2 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[2]), 0); + __m128i k0 = _mm_loadl_epi64((__m128i*)(kx + 1)); + k0 = _mm_unpacklo_epi64(k0, k0); k0 = _mm_packs_epi32(k0, k0); - k1 = _mm_packs_epi32(k1, k1); - k2 = _mm_packs_epi32(k2, k2); for( ; i <= width - 16; i += 16, src += 16 ) { - __m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3; - x0 = _mm_loadu_si128((__m128i*)(src + cn)); - x2 = _mm_loadu_si128((__m128i*)(src - cn)); - y0 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z)); - x0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z)); + __m128i x0 = _mm_loadu_si128((__m128i*)(src + cn)); + __m128i x1 = _mm_loadu_si128((__m128i*)(src - cn)); - x2 = _mm_mulhi_epi16(x0, k1); - x0 = _mm_mullo_epi16(x0, k1); - z0 = _mm_unpacklo_epi16(x0, x2); - z1 = _mm_unpackhi_epi16(x0, x2); - y1 = _mm_mulhi_epi16(y0, k1); - y0 = _mm_mullo_epi16(y0, k1); - z2 = _mm_unpacklo_epi16(y0, y1); - z3 = _mm_unpackhi_epi16(y0, y1); + __m128i x2 = _mm_unpackhi_epi8(x0, z); + __m128i x3 = _mm_unpackhi_epi8(x1, z); + x0 = _mm_unpacklo_epi8(x0, z); + x1 = _mm_unpacklo_epi8(x1, z); + __m128i x5 = _mm_sub_epi16(x2, x3); + __m128i x4 = _mm_sub_epi16(x0, x1); - x0 = _mm_loadu_si128((__m128i*)(src + cn*2)); - x1 = _mm_loadu_si128((__m128i*)(src - cn*2)); - y1 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z)); - y0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z)); + __m128i x6 = _mm_loadu_si128((__m128i*)(src + cn * 2)); + __m128i x7 = _mm_loadu_si128((__m128i*)(src - cn * 2)); - t1 = _mm_mulhi_epi16(y0, k2); - t0 = _mm_mullo_epi16(y0, k2); - y0 = _mm_mullo_epi16(y1, k2); - y1 = _mm_mulhi_epi16(y1, k2); - z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(t0, t1)); - z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(t0, t1)); - z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1)); - z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1)); + __m128i x8 = _mm_unpackhi_epi8(x6, z); + __m128i x9 = _mm_unpackhi_epi8(x7, z); + x6 = _mm_unpacklo_epi8(x6, z); + x7 = _mm_unpacklo_epi8(x7, z); + __m128i x11 = _mm_sub_epi16(x8, x9); + __m128i x10 = _mm_sub_epi16(x6, x7); - _mm_store_si128((__m128i*)(dst + i), z0); - _mm_store_si128((__m128i*)(dst + i + 4), z1); - _mm_store_si128((__m128i*)(dst + i + 8), z2); - _mm_store_si128((__m128i*)(dst + i + 12), z3); + __m128i x13 = _mm_unpackhi_epi16(x5, x11); + __m128i x12 = _mm_unpackhi_epi16(x4, x10); + x5 = _mm_unpacklo_epi16(x5, x11); + x4 = _mm_unpacklo_epi16(x4, x10); + x5 = _mm_madd_epi16(x5, k0); + x4 = _mm_madd_epi16(x4, k0); + x13 = _mm_madd_epi16(x13, k0); + x12 = _mm_madd_epi16(x12, k0); + + _mm_store_si128((__m128i*)(dst + i), x4); + _mm_store_si128((__m128i*)(dst + i + 4), x12); + _mm_store_si128((__m128i*)(dst + i + 8), x5); + _mm_store_si128((__m128i*)(dst + i + 12), x13); } } } @@ -870,19 +845,18 @@ struct SymmRowSmallVec_8u32s kx -= _ksize/2; for( ; i <= width - 4; i += 4, src += 4 ) { - __m128i f, s0 = z, x0, x1; + __m128i s0 = z; for( k = j = 0; k < _ksize; k++, j += cn ) { - f = _mm_cvtsi32_si128(kx[k]); + __m128i f = _mm_cvtsi32_si128(kx[k]); f = _mm_shuffle_epi32(f, 0); - f = _mm_packs_epi32(f, f); - x0 = _mm_cvtsi32_si128(*(const int*)(src + j)); + __m128i x0 = _mm_cvtsi32_si128(*(const int*)(src + j)); x0 = _mm_unpacklo_epi8(x0, z); - x1 = _mm_mulhi_epi16(x0, f); - x0 = _mm_mullo_epi16(x0, f); - s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1)); + x0 = _mm_unpacklo_epi16(x0, z); + x0 = _mm_madd_epi16(x0, f); + s0 = _mm_add_epi32(s0, x0); } _mm_store_si128((__m128i*)(dst + i), s0); } From 2deda0e868d87e0e5a5be3eccd8539073881b0c6 Mon Sep 17 00:00:00 2001 From: arybnikov Date: Fri, 15 Jul 2016 12:15:31 +0300 Subject: [PATCH 069/153] Added tests for issues ##4515, 6544 --- modules/imgproc/test/test_fitellipse.cpp | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 modules/imgproc/test/test_fitellipse.cpp diff --git a/modules/imgproc/test/test_fitellipse.cpp b/modules/imgproc/test/test_fitellipse.cpp new file mode 100644 index 0000000000..57ad068309 --- /dev/null +++ b/modules/imgproc/test/test_fitellipse.cpp @@ -0,0 +1,70 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2016, Itseez, Inc, all rights reserved. + +#include "test_precomp.hpp" +#include +#include + +using namespace cv; +using namespace std; + +// return true if point lies inside ellipse +static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) { + Point2f to_pt = pt - el.center; + double pt_angle = atan2(to_pt.y, to_pt.x); + double el_angle = el.angle * CV_PI / 180; + double x_dist = 0.5 * el.size.width * cos(pt_angle + el_angle); + double y_dist = 0.5 * el.size.height * sin(pt_angle + el_angle); + double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist); + return norm(to_pt) < el_dist; +} + +// Return true if mass center of fitted points lies inside ellipse +static bool fit_and_check_ellipse(const vector& pts) { + RotatedRect ellipse = fitEllipse(pts); + + Point2f mass_center; + for (size_t i = 0; i < pts.size(); i++) { + mass_center += pts[i]; + } + mass_center /= (float)pts.size(); + + return check_pt_in_ellipse(mass_center, ellipse); +} + +TEST(Imgproc_FitEllipse_Issue_4515, DISABLED_accuracy) { + vector pts; + pts.push_back(Point2f(327, 317)); + pts.push_back(Point2f(328, 316)); + pts.push_back(Point2f(329, 315)); + pts.push_back(Point2f(330, 314)); + pts.push_back(Point2f(331, 314)); + pts.push_back(Point2f(332, 314)); + pts.push_back(Point2f(333, 315)); + pts.push_back(Point2f(333, 316)); + pts.push_back(Point2f(333, 317)); + pts.push_back(Point2f(333, 318)); + pts.push_back(Point2f(333, 319)); + pts.push_back(Point2f(333, 320)); + + EXPECT_TRUE(fit_and_check_ellipse(pts)); +} + +TEST(Imgproc_FitEllipse_Issue_6544, DISABLED_accuracy) { + vector pts; + pts.push_back(Point2f(924.784f, 764.160f)); + pts.push_back(Point2f(928.388f, 615.903f)); + pts.push_back(Point2f(847.4f, 888.014f)); + pts.push_back(Point2f(929.406f, 741.675f)); + pts.push_back(Point2f(904.564f, 825.605f)); + pts.push_back(Point2f(926.742f, 760.746f)); + pts.push_back(Point2f(863.479f, 873.406f)); + pts.push_back(Point2f(910.987f, 808.863f)); + pts.push_back(Point2f(929.145f, 744.976f)); + pts.push_back(Point2f(917.474f, 791.823f)); + + EXPECT_TRUE(fit_and_check_ellipse(pts)); +} From 13d1ee10be80e40df015ac5cec82311ca690c321 Mon Sep 17 00:00:00 2001 From: Andreas Franek Date: Mon, 18 Jul 2016 14:31:16 +0200 Subject: [PATCH 070/153] replaced static const members with static functions for msvc cpmpatability --- modules/cudaoptflow/src/cuda/pyrlk.cu | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/cudaoptflow/src/cuda/pyrlk.cu b/modules/cudaoptflow/src/cuda/pyrlk.cu index 5c81edface..2f2865057f 100644 --- a/modules/cudaoptflow/src/cuda/pyrlk.cu +++ b/modules/cudaoptflow/src/cuda/pyrlk.cu @@ -347,13 +347,19 @@ namespace pyrlk template struct DenormalizationFactor { - static const float factor = 1.0; + static __device__ __forceinline__ float factor() + { + return 1.0f; + } }; template <> struct DenormalizationFactor { - static const float factor = 255.0; + static __device__ __forceinline__ float factor() + { + return 255.0f; + } }; template @@ -544,7 +550,7 @@ namespace pyrlk nextPts[blockIdx.x] = nextPt; if (calcErr) - err[blockIdx.x] = static_cast(errval) / (::min(cn, 3) * c_winSize_x * c_winSize_y) * DenormalizationFactor::factor; + err[blockIdx.x] = static_cast(errval) / (::min(cn, 3) * c_winSize_x * c_winSize_y) * DenormalizationFactor::factor(); } } From 617df091438f94d50dce8aa32d83392103bc3a5b Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 15:54:38 +0800 Subject: [PATCH 071/153] Modify Base64 functions and add test and documentation Major changes: - modify the Base64 functions to compatible with `cvWriteRawData` and so on. - add a Base64 flag for FileStorage and outputs raw data in Base64 automatically. - complete all testing and documentation. --- modules/core/include/opencv2/core/core_c.h | 58 +- .../core/include/opencv2/core/persistence.hpp | 9 +- modules/core/include/opencv2/core/types_c.h | 2 + modules/core/perf/perf_io_base64.cpp | 86 +++ modules/core/src/persistence.cpp | 711 ++++++++++++------ modules/core/test/test_io.cpp | 147 ---- modules/core/test/test_io_base64.cpp | 270 +++++++ modules/ml/test/test_save_load.cpp | 6 +- 8 files changed, 911 insertions(+), 378 deletions(-) create mode 100644 modules/core/perf/perf_io_base64.cpp create mode 100644 modules/core/test/test_io_base64.cpp diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index a0ed632642..94ba1fc034 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1976,8 +1976,19 @@ CVAPI(void) cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, The function opens file storage for reading or writing data. In the latter case, a new file is created or an existing file is rewritten. The type of the read or written file is determined by the -filename extension: .xml for XML and .yml or .yaml for YAML. The function returns a pointer to the -CvFileStorage structure. If the file cannot be opened then the function returns NULL. +filename extension: .xml for XML and .yml or .yaml for YAML. + +At the same time, it also supports adding parameters like "example.xml?base64". +@code + CvFileStorage* fs = cvOpenFileStorage( "example.yml?base64", 0, CV_STORAGE_WRITE ); +@endcode +it's exactly the same as +@code + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64 ); +@endcode + +The function returns a pointer to the CvFileStorage structure. +If the file cannot be opened then the function returns NULL. @param filename Name of the file associated with the storage @param memstorage Memory storage used for temporary data and for : storing dynamic structures, such as CvSeq or CvGraph . If it is NULL, a temporary memory @@ -1985,6 +1996,7 @@ CvFileStorage structure. If the file cannot be opened then the function returns @param flags Can be one of the following: > - **CV_STORAGE_READ** the storage is open for reading > - **CV_STORAGE_WRITE** the storage is open for writing + (use **CV_STORAGE_WRITE | CV_STORAGE_WRITE_BASE64** to write rawdata in Base64) @param encoding */ CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, @@ -2162,7 +2174,7 @@ the file with multiple streams looks like this: @endcode The YAML file will look like this: @code{.yaml} - %YAML:1.0 + %YAML 1.0 # stream #1 data ... --- @@ -2187,6 +2199,46 @@ to a sequence rather than a map. CVAPI(void) cvWriteRawData( CvFileStorage* fs, const void* src, int len, const char* dt ); +/** @brief Writes multiple numbers in Base64. + +If either CV_STORAGE_WRITE_BASE64 or cv::FileStorage::WRITE_BASE64 is used, +this function will be the same as cvWriteRawData. If neither, the main +difference is that it outputs a sequence in Base64 encoding rather than +in plain text. + +This function can only be used to write a sequence with a type "binary". + +Consider the following two examples where their output is the same: +@code + std::vector rawdata(10, 0x00010203); + // without the flag CV_STORAGE_WRITE_BASE64. + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE ); + // both CV_NODE_SEQ and "binary" are necessary. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary"); + cvWriteRawDataBase64(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); +@endcode +and +@code + std::vector rawdata(10, 0x00010203); + // with the flag CV_STORAGE_WRITE_BASE64. + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE_BASE64); + // parameter, typename "binary" could be omitted. + cvStartWriteStruct(fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW); + cvWriteRawData(fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(fs); + cvReleaseFileStorage( &fs ); +@endcode + +@param fs File storage +@param src Pointer to the written array +@param len Number of the array elements to write +@param dt Specification of each array element, see @ref format_spec "format specification" +*/ +CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* _data, + int len, const char* dt ); + /** @brief Returns a unique pointer for a given name. The function returns a unique pointer for each particular file node name. This pointer can be then diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 65a1ff4c4c..75f0c32bd2 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -311,7 +311,10 @@ public: FORMAT_MASK = (7<<3), //!< mask for format flags FORMAT_AUTO = 0, //!< flag, auto format FORMAT_XML = (1<<3), //!< flag, XML format - FORMAT_YAML = (2<<3) //!< flag, YAML format + FORMAT_YAML = (2<<3), //!< flag, YAML format + + BASE64 = 64, //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64) + WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64 }; enum { @@ -354,7 +357,9 @@ public: Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify - the output file format (e.g. mydata.xml, .yml etc.). + the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters. + You can use this format, "*?base64" (e.g. "file.xml?base64"), as an alternative to + FileStorage::BASE64 flag. Note: it is case sensitive. @param flags Mode of operation. One of FileStorage::Mode @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it. diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index cb39587a9a..e693aa4724 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -1669,6 +1669,8 @@ typedef struct CvFileStorage CvFileStorage; #define CV_STORAGE_FORMAT_AUTO 0 #define CV_STORAGE_FORMAT_XML 8 #define CV_STORAGE_FORMAT_YAML 16 +#define CV_STORAGE_BASE64 64 +#define CV_STORAGE_WRITE_BASE64 (CV_STORAGE_BASE64 | CV_STORAGE_WRITE) /** @brief List of attributes. : diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp new file mode 100644 index 0000000000..693c1cc132 --- /dev/null +++ b/modules/core/perf/perf_io_base64.cpp @@ -0,0 +1,86 @@ +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace perf; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef std::tr1::tuple Size_MatType_Str_t; +typedef TestBaseWithParam Size_Mat_StrType; + +#define MAT_SIZES ::perf::sz1080p/*, ::perf::sz4320p*/ +#define MAT_TYPES CV_8UC1, CV_32FC1 +#define FILE_EXTENSION String(".xml"), String(".yml") + +PERF_TEST_P(Size_Mat_StrType, fs_text, + testing::Combine(testing::Values(MAT_SIZES), + testing::Values(MAT_TYPES), + testing::Values(FILE_EXTENSION)) + ) +{ + Size size = get<0>(GetParam()); + int type = get<1>(GetParam()); + String ext = get<2>(GetParam()); + + Mat src(size.height, size.width, type); + Mat dst = src.clone(); + + declare.in(src, WARMUP_RNG).out(dst); + + cv::String file_name = cv::tempfile(ext.c_str()); + cv::String key = "test_mat"; + + TEST_CYCLE_MULTIRUN(4) + { + { + FileStorage fs(file_name, cv::FileStorage::WRITE); + fs << key << src; + fs.release(); + } + { + FileStorage fs(file_name, cv::FileStorage::READ); + fs[key] >> dst; + fs.release(); + } + } + + remove(file_name.c_str()); + + SANITY_CHECK(dst, 1); +} + +PERF_TEST_P(Size_Mat_StrType, fs_base64, + testing::Combine(testing::Values(MAT_SIZES), + testing::Values(MAT_TYPES), + testing::Values(FILE_EXTENSION)) + ) +{ + Size size = get<0>(GetParam()); + int type = get<1>(GetParam()); + String ext = get<2>(GetParam()); + + Mat src(size.height, size.width, type); + Mat dst = src.clone(); + + cv::String file_name = cv::tempfile(ext.c_str()); + cv::String key = "test_mat"; + + declare.in(src, WARMUP_RNG).out(dst); + TEST_CYCLE_MULTIRUN(4) + { + { + FileStorage fs(file_name, cv::FileStorage::WRITE_BASE64); + fs << key << src; + fs.release(); + } + { + FileStorage fs(file_name, cv::FileStorage::READ); + fs[key] >> dst; + fs.release(); + } + } + + remove(file_name.c_str()); + SANITY_CHECK(dst, 1); +} diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 4d99a4a275..6eb3b0c75a 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -243,6 +243,17 @@ typedef struct CvFileStorage std::deque* outbuf; base64::Base64Writer * base64_writer; + bool is_default_using_base64; + enum Base64State { + Uncertain, + NotUse, + InUse, + } state_of_writing_base64; /**< used in WriteRawData only */ + + bool is_write_struct_delayed; + char* delayed_struct_key; + int delayed_struct_flags; + char* delayed_type_name; bool is_opened; } @@ -270,21 +281,23 @@ namespace base64 bool base64_valid (uint8_t const * src, size_t off, size_t cnt); bool base64_valid ( char const * src, size_t off = 0U, size_t cnt = 0U); - size_t base64_encode_buffer_size(size_t cnt); + size_t base64_encode_buffer_size(size_t cnt, bool is_end_with_zero = true); - size_t base64_decode_buffer_size(size_t cnt); + size_t base64_decode_buffer_size(size_t cnt, bool is_end_with_zero = true); + size_t base64_decode_buffer_size(size_t cnt, char const * src, bool is_end_with_zero = true); + size_t base64_decode_buffer_size(size_t cnt, uchar const * src, bool is_end_with_zero = true); /* binary */ - template inline size_t to_binary(_uint_t val, uchar * cur); - template<> inline size_t to_binary(double val, uchar * cur); - template<> inline size_t to_binary(float val, uchar * cur); + template inline size_t to_binary(_uint_t val, uchar * cur); + template<> inline size_t to_binary(double val, uchar * cur); + template<> inline size_t to_binary(float val, uchar * cur); template inline size_t to_binary(uchar const * val, uchar * cur); - template inline size_t binary_to(uchar const * cur, _uint_t & val); - template<> inline size_t binary_to(uchar const * cur, double & val); - template<> inline size_t binary_to(uchar const * cur, float & val); - template inline size_t binary_to(uchar const * cur, uchar * val); + template inline size_t binary_to(uchar const * cur, _uint_t & val); + template<> inline size_t binary_to(uchar const * cur, double & val); + template<> inline size_t binary_to(uchar const * cur, float & val); + template inline size_t binary_to(uchar const * cur, uchar * val); class MatToBinaryConvertor; class RawDataToBinaryConvertor; @@ -313,22 +326,37 @@ namespace base64 class Base64ContextEmitter; + class Base64Writer + { + public: + Base64Writer(::CvFileStorage * fs); + ~Base64Writer(); + void write(const void* _data, size_t len, const char* dt); + template void write(_to_binary_convertor_t & convertor, const char* dt); + + private: + void check_dt(const char* dt); + + private: + + ::CvFileStorage * file_storage; + Base64ContextEmitter * emitter; + std::string data_type_string; + }; + /* other */ - std::string make_base64_header(int byte_size, const char * dt); + std::string make_base64_header(const char * dt); - bool read_base64_header(std::string const & header, int & byte_size, std::string & dt); + bool read_base64_header(std::vector const & header, std::string & dt); void make_seq(void * binary_data, int elem_cnt, const char * dt, CvSeq & seq); /* sample */ - void cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt); - void cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len); - void cvEndWriteRawData_Base64(::CvFileStorage * fs); + void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt); - void cvWriteRawData_Base64(::cv::FileStorage & fs, const void* _data, int len, const char* dt); - void cvWriteMat_Base64(CvFileStorage * fs, const char * name, ::cv::Mat const & mat); + void cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat); } @@ -1031,6 +1059,184 @@ static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr ) return fval; } +static std::vector analyze_file_name( std::string const & file_name ) +{ + static const char parameter_begin = '?'; + static const char parameter_separator = '&'; + std::vector result; + + size_t beg = file_name.find_last_of(parameter_begin); + size_t end = file_name.size(); + result.push_back(file_name.substr(0U, beg)); + + if ( beg != std::string::npos ) + { + beg ++; + for ( size_t param_beg = beg, param_end = beg; + param_end < end; + param_beg = param_end + 1U ) + { + param_end = file_name.find_first_of( parameter_separator, param_beg ); + if ( (param_end == std::string::npos || param_end != param_beg) && param_beg + 1U < end ) + { + result.push_back( file_name.substr( param_beg, param_end - param_beg ) ); + } + } + } + + return result; +} + +static bool is_param_exist( std::vector & const params, std::string & const param ) +{ + if ( params.size() < 2U ) + return false; + + return std::find(params.begin(), params.end(), param) != params.end(); +} + +static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64State state ) +{ + const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; + const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; + + /* like a finite state machine */ + switch (fs->state_of_writing_base64) + { + case CvFileStorage::Base64State::Uncertain: + switch (state) + { + case CvFileStorage::Base64State::InUse: + CV_DbgAssert( fs->base64_writer == 0 ); + fs->base64_writer = new base64::Base64Writer( fs ); + break; + case CvFileStorage::Base64State::Uncertain: + break; + case CvFileStorage::Base64State::NotUse: + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + case CvFileStorage::Base64State::InUse: + switch (state) + { + case CvFileStorage::Base64State::InUse: + case CvFileStorage::Base64State::NotUse: + CV_Error( CV_StsError, err_unable_to_switch ); + break; + case CvFileStorage::Base64State::Uncertain: + delete fs->base64_writer; + fs->base64_writer = 0; + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + case CvFileStorage::Base64State::NotUse: + switch (state) + { + case CvFileStorage::Base64State::InUse: + case CvFileStorage::Base64State::NotUse: + CV_Error( CV_StsError, err_unable_to_switch ); + break; + case CvFileStorage::Base64State::Uncertain: + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + break; + default: + CV_Error( CV_StsError, err_unkonwn_state ); + break; + } + + fs->state_of_writing_base64 = state; +} + + +static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_type_to_base64 = false ) +{ + if ( fs->is_write_struct_delayed ) + { + /* save data to prevent recursive call errors */ + char * struct_key = 0; + char * type_name = 0; + int struct_flags = fs->delayed_struct_flags; + + if ( fs->delayed_struct_key != 0 ) + { + struct_key = new char[strlen(fs->delayed_struct_key) + 1U]; + strcpy(struct_key, fs->delayed_struct_key); + } + if ( fs->delayed_type_name != 0 ) + { + type_name = new char[strlen(type_name) + 1U]; + strcpy(type_name, fs->delayed_type_name); + } + + /* reset */ + delete fs->delayed_struct_key; + delete fs->delayed_type_name; + fs->delayed_struct_key = 0; + fs->delayed_struct_flags = 0; + fs->delayed_type_name = 0; + + fs->is_write_struct_delayed = false; + + /* call */ + if ( change_type_to_base64 ) + { + fs->start_write_struct( fs, struct_key, struct_flags, "binary"); + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + } + else + { + fs->start_write_struct( fs, struct_key, struct_flags, type_name); + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + + delete struct_key; + delete type_name; + } +} + + +static void make_write_struct_delayed( + CvFileStorage* fs, + const char* key, + int struct_flags, + const char* type_name ) +{ + CV_Assert( fs->is_write_struct_delayed == false ); + CV_DbgAssert( fs->delayed_struct_key == 0 ); + CV_DbgAssert( fs->delayed_struct_flags == 0 ); + CV_DbgAssert( fs->delayed_type_name == 0 ); + + fs->delayed_struct_flags = struct_flags; + + if ( key != 0 ) + { + fs->delayed_struct_key = new char[strlen(key) + 1U]; + strcpy(fs->delayed_struct_key, key); + } + + if ( type_name != 0 ) + { + fs->delayed_type_name = new char[strlen(type_name) + 1U]; + strcpy(fs->delayed_type_name, type_name); + } + + fs->is_write_struct_delayed = true; +} + /****************************************************************************************\ * YAML Parser * @@ -1119,40 +1325,41 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN /* calc (decoded) total_byte_size from header */ std::string dt; - int total_byte_size = -1; { if (end - beg < static_cast(base64::ENCODED_HEADER_SIZE)) CV_PARSE_ERROR("Unrecognized Base64 header"); std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); - std::istringstream iss(header.data()); - - if (!(iss >> total_byte_size) || total_byte_size < 0) - CV_PARSE_ERROR("Cannot parse size in Base64 header"); - if (!(iss >> dt) || dt.empty()) + if ( !base64::read_base64_header(header, dt) || dt.empty() ) CV_PARSE_ERROR("Cannot parse dt in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } - /* buffer for decoded data(exclude header) */ - std::vector buffer(total_byte_size + 4); + /* get all Base64 data */ + std::string base64_buffer; + base64_buffer.reserve( 16U * 1024U * 1024U ); + while( beg < end ) { - base64::Base64ContextParser parser(buffer.data(), total_byte_size + 4); - - /* decoding */ - while(beg < end) - { - /* save this part [beg, end) */ - parser.read((const uchar *)beg, (const uchar *)end); - - beg = end; - - /* find next part */ - icvYMLGetMultilineStringContent(fs, beg, indent, beg, end); - } + base64_buffer.append( beg, end ); + beg = end; + icvYMLGetMultilineStringContent( fs, beg, indent, beg, end ); } + if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + CV_PARSE_ERROR( "Invalid Base64 data." ); + + /* buffer for decoded data(exclude header) */ + std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); + int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + { + base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); + const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); + const uchar * buffer_end = buffer_beg + base64_buffer.size(); + parser.read( buffer_beg, buffer_end ); + parser.flush(); + } + /* save as CvSeq */ int elem_size = ::icvCalcStructSize(dt.c_str(), 0); if (total_byte_size % elem_size != 0) @@ -1160,9 +1367,10 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN int elem_cnt = total_byte_size / elem_size; node->tag = CV_NODE_NONE; - int struct_flags = CV_NODE_FLOW + CV_NODE_SEQ; /* after icvFSCreateCollection, node->tag == struct_flags */ + int struct_flags = CV_NODE_FLOW | CV_NODE_SEQ; + /* after icvFSCreateCollection, node->tag == struct_flags */ icvFSCreateCollection(fs, struct_flags, node); - base64::make_seq(buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); + base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); if (fs->dummy_eof) { /* end of file */ @@ -1621,6 +1829,16 @@ icvYMLParse( CvFileStorage* fs ) static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "At present, output Base64 data only." ); + } + int i, keylen = 0; int datalen = 0; int struct_flags; @@ -2034,17 +2252,17 @@ static void icvXMLGetMultilineStringContent(CvFileStorage* fs, ptr = icvXMLSkipSpaces(fs, ptr, CV_XML_INSIDE_TAG); beg = ptr; end = ptr; - if (fs->dummy_eof) + if ( fs->dummy_eof ) return ; /* end of file */ - if (*beg == '<') + if ( *beg == '<' ) return; /* end of string */ /* find end */ - while(cv_isprint(*ptr)) /* no check for base64 string */ + while( cv_isprint(*ptr) ) /* no check for base64 string */ ++ ptr; - if (*ptr == '\0') - CV_PARSE_ERROR("Unexpected end of line"); + if ( *ptr == '\0' ) + CV_PARSE_ERROR( "Unexpected end of line" ); end = ptr; } @@ -2061,48 +2279,52 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) /* calc (decoded) total_byte_size from header */ std::string dt; - int total_byte_size = -1; { if (end - beg < static_cast(base64::ENCODED_HEADER_SIZE)) CV_PARSE_ERROR("Unrecognized Base64 header"); std::vector header(base64::HEADER_SIZE + 1, ' '); base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE); - std::istringstream iss(header.data()); - if (!(iss >> total_byte_size) || total_byte_size < 0) - CV_PARSE_ERROR("Cannot parse size in Base64 header"); - if (!(iss >> dt) || dt.empty()) + if ( !base64::read_base64_header(header, dt) || dt.empty() ) CV_PARSE_ERROR("Cannot parse dt in Base64 header"); beg += base64::ENCODED_HEADER_SIZE; } - /* alloc buffer for all decoded data(include header) */ - std::vector buffer(total_byte_size + 4); + /* get all Base64 data */ + std::string base64_buffer; + base64_buffer.reserve( 16U * 1024U * 1024U ); + while( beg < end ) { - base64::Base64ContextParser parser(buffer.data(), total_byte_size + 4); + base64_buffer.append( beg, end ); + beg = end; + icvXMLGetMultilineStringContent( fs, beg, beg, end ); + } + if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + CV_PARSE_ERROR( "Invalid Base64 data." ); - /* decoding */ - while(beg < end) - { - /* save this part [beg, end) */ - parser.read((const uchar *)beg, (const uchar *)end); - beg = end; - /* find next part */ - icvXMLGetMultilineStringContent(fs, beg, beg, end); - } + /* alloc buffer for all decoded data(include header) */ + std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); + int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + { + base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); + const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); + const uchar * buffer_end = buffer_beg + base64_buffer.size(); + parser.read( buffer_beg, buffer_end ); + parser.flush(); } /* save as CvSeq */ int elem_size = ::icvCalcStructSize(dt.c_str(), 0); if (total_byte_size % elem_size != 0) - CV_PARSE_ERROR("Byte size not match elememt size"); + CV_PARSE_ERROR("data size not matches elememt size"); int elem_cnt = total_byte_size / elem_size; node->tag = CV_NODE_NONE; - int struct_flags = CV_NODE_SEQ; /* after icvFSCreateCollection, node->tag == struct_flags */ + int struct_flags = CV_NODE_SEQ; + /* after icvFSCreateCollection, node->tag == struct_flags */ icvFSCreateCollection(fs, struct_flags, node); - base64::make_seq(buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); + base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq); if (fs->dummy_eof) { /* end of file */ @@ -2757,6 +2979,16 @@ icvXMLStartNextStream( CvFileStorage* fs ) static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); + } + if( CV_NODE_IS_MAP(fs->struct_flags) || (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) ) { @@ -2964,15 +3196,24 @@ icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment ) \****************************************************************************************/ CV_IMPL CvFileStorage* -cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, const char* encoding ) +cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const char* encoding ) { CvFileStorage* fs = 0; int default_block_size = 1 << 18; bool append = (flags & 3) == CV_STORAGE_APPEND; bool mem = (flags & CV_STORAGE_MEMORY) != 0; bool write_mode = (flags & 3) != 0; + bool write_base64 = write_mode && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; + const char * filename = 0; + + std::vector params = analyze_file_name( query ); + if ( !params.empty() ) + filename = params.begin()->c_str(); + + if (write_base64 == false && is_param_exist( params, std::string("base64") ) ) + write_base64 = true; if( !filename || filename[0] == '\0' ) { @@ -3073,6 +3314,16 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co fs->struct_flags = CV_NODE_EMPTY; fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 ); fs->buffer_end = fs->buffer_start + buf_size; + + fs->base64_writer = 0; + fs->is_default_using_base64 = write_base64; + fs->state_of_writing_base64 = CvFileStorage::Base64State::Uncertain; + + fs->is_write_struct_delayed = false; + fs->delayed_struct_key = 0; + fs->delayed_struct_flags = 0; + fs->delayed_type_name = 0; + if( fs->fmt == CV_STORAGE_FORMAT_XML ) { size_t file_size = fs->file ? (size_t)ftell( fs->file ) : (size_t)0; @@ -3247,7 +3498,48 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name, CvAttrList /*attributes*/ ) { CV_CHECK_OUTPUT_FILE_STORAGE(fs); - fs->start_write_struct( fs, key, struct_flags, type_name ); + check_if_write_struct_is_delayed( fs ); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::NotUse ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain + && + CV_NODE_IS_SEQ(struct_flags) + && + fs->is_default_using_base64 + && + type_name == 0 + ) + { + /* Uncertain if output Base64 data */ + make_write_struct_delayed( fs, key, struct_flags, type_name ); + } + else if ( type_name && memcmp(type_name, "binary", 6) == 0 ) + { + /* Must output Base64 data */ + if ( !CV_NODE_IS_SEQ(struct_flags) ) + CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); + else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); + + fs->start_write_struct( fs, key, struct_flags, type_name ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + } + else + { + /* Won't output Base64 data */ + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); + + fs->start_write_struct( fs, key, struct_flags, type_name ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } } @@ -3255,6 +3547,11 @@ CV_IMPL void cvEndWriteStruct( CvFileStorage* fs ) { CV_CHECK_OUTPUT_FILE_STORAGE(fs); + check_if_write_struct_is_delayed( fs ); + + if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + fs->end_write_struct( fs ); } @@ -3432,6 +3729,17 @@ icvDecodeSimpleFormat( const char* dt ) CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { + if (fs->is_default_using_base64 || + fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + { + base64::cvWriteRawDataBase64( fs, _data, len, dt ); + return; + } + else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + { + switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + } + const char* data0 = (const char*)_data; int offset = 0; int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k, fmt_pair_count; @@ -3760,15 +4068,15 @@ icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node ) break; case CV_NODE_SEQ: case CV_NODE_MAP: - fs->start_write_struct( fs, name, CV_NODE_TYPE(node->tag) + + cvStartWriteStruct( fs, name, CV_NODE_TYPE(node->tag) + (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0), node->info ? node->info->type_name : 0 ); icvWriteCollection( fs, node ); - fs->end_write_struct( fs ); + cvEndWriteStruct( fs ); break; case CV_NODE_NONE: - fs->start_write_struct( fs, name, CV_NODE_SEQ, 0 ); - fs->end_write_struct( fs ); + cvStartWriteStruct( fs, name, CV_NODE_SEQ, 0 ); + cvEndWriteStruct( fs ); break; default: CV_Error( CV_StsBadFlag, "Unknown type of file node" ); @@ -6226,14 +6534,29 @@ bool base64::base64_valid(char const * src, size_t off, size_t cnt) return base64_valid(reinterpret_cast(src), off, cnt); } -size_t base64::base64_encode_buffer_size(size_t cnt) +size_t base64::base64_encode_buffer_size(size_t cnt, bool is_end_with_zero) { - return size_t((cnt + 2U) / 3U * 4U + 1U); + size_t additional = static_cast(is_end_with_zero == true); + return (cnt + 2U) / 3U * 4U + additional; } -size_t base64::base64_decode_buffer_size(size_t cnt) +size_t base64::base64_decode_buffer_size(size_t cnt, bool is_end_with_zero) { - return size_t(cnt / 4U * 3U + 1U); + size_t additional = static_cast(is_end_with_zero == true); + return cnt / 4U * 3U + additional; +} + +size_t base64::base64_decode_buffer_size(size_t cnt, char const * src, bool is_end_with_zero) +{ + return base64_decode_buffer_size(cnt, reinterpret_cast(src), is_end_with_zero); +} + +size_t base64::base64_decode_buffer_size(size_t cnt, uchar const * src, bool is_end_with_zero) +{ + size_t padding_cnt = 0U; + for (uchar const * ptr = src + cnt - 1U; *ptr == base64_padding; ptr--) + padding_cnt ++; + return base64_decode_buffer_size(cnt, is_end_with_zero) - padding_cnt; } /**************************************************************************** @@ -6308,13 +6631,10 @@ binary_to(uchar const * cur, uchar * val) * others ***************************************************************************/ -std::string base64::make_base64_header(int byte_size, const char * dt) +std::string base64::make_base64_header(const char * dt) { - int size = byte_size; - std::ostringstream oss; - oss << size << ' ' - << dt << ' '; + oss << dt << ' '; std::string buffer(oss.str()); CV_Assert(buffer.size() < HEADER_SIZE); @@ -6325,10 +6645,10 @@ std::string base64::make_base64_header(int byte_size, const char * dt) return buffer; } -bool base64::read_base64_header(std::string const & header, int & byte_size, std::string & dt) +bool base64::read_base64_header(std::vector const & header, std::string & dt) { - std::istringstream iss(header); - return static_cast(iss >> byte_size >> dt); + std::istringstream iss(header.data()); + return static_cast(iss >> dt); } /**************************************************************************** @@ -6351,10 +6671,9 @@ base64::Base64ContextParser::Base64ContextParser(uchar * buffer, size_t size) base64::Base64ContextParser::~Base64ContextParser() { - if (src_cur != src_beg) { - /* encode the rest binary data to base64 buffer */ + /* encode the rest binary data to base64 buffer */ + if (src_cur != src_beg) flush(); - } } base64::Base64ContextParser & base64::Base64ContextParser:: @@ -6383,9 +6702,12 @@ read(const uchar * beg, const uchar * end) bool base64::Base64ContextParser::flush() { - if (!base64_valid(src_beg, 0U, src_cur - src_beg)) + if ( !base64_valid(src_beg, 0U, src_cur - src_beg) ) return false; + if ( src_cur == src_beg ) + return true; + uchar * buffer = binary_buffer.data(); size_t len = base64_decode(src_beg, buffer, 0U, src_cur - src_beg); src_cur = src_beg; @@ -6514,7 +6836,7 @@ public: private: /* because of Base64, we must keep its length a multiple of 3 */ - static const size_t BUFFER_LEN = 51U; + static const size_t BUFFER_LEN = 48U; // static_assert(BUFFER_LEN % 3 == 0, "BUFFER_LEN is invalid"); private: @@ -6584,17 +6906,17 @@ public: { CV_DbgAssert(*this); - /* copy to dst */ + /* [1]copy to dst */ dst += to_binary_func(row_begin + x, dst); - /* move to next */ + /* [2]move to next */ x += step; if (x >= x_max) { - /* when x arrive end, reset it and increase y */ + /* when x arrive end, reset x and increase y */ x = 0U; ++ y; if (y >= y_max) { - /* when y arrive end, reset it and increase iter */ + /* when y arrive end, reset y and increase iter */ y = 0U; ++ mat_iter; if (mat_iter == mats.end()) { @@ -6935,68 +7257,55 @@ private: * Wapper ***************************************************************************/ -class base64::Base64Writer + +base64::Base64Writer::Base64Writer(::CvFileStorage * fs) + : file_storage(fs) + , emitter(new Base64ContextEmitter(fs)) + , data_type_string() { -public: + CV_CHECK_OUTPUT_FILE_STORAGE(fs); + icvFSFlush(fs); +} - Base64Writer(::CvFileStorage * fs, const char * name, int len, const char* dt) - : file_storage(fs) - , emitter(fs) - , remaining_data_length(len) - , data_type_string(dt) - { - CV_CHECK_OUTPUT_FILE_STORAGE(fs); +void base64::Base64Writer::write(const void* _data, size_t len, const char* dt) +{ + check_dt(dt); - cvStartWriteStruct(fs, name, CV_NODE_SEQ, "binary"); - icvFSFlush(fs); + RawDataToBinaryConvertor convertor( + _data, static_cast(len), data_type_string.c_str() + ); + emitter->write(convertor); +} + +template inline +void base64::Base64Writer::write(_to_binary_convertor_t & convertor, const char* dt) +{ + check_dt(dt); + emitter->write(convertor); +} + +base64::Base64Writer::~Base64Writer() +{ + delete emitter; +} + +void base64::Base64Writer::check_dt(const char* dt) +{ + if ( dt == 0 ) + CV_Error( CV_StsBadArg, "Invalid \'dt\'." ); + else if (data_type_string.empty()) { + data_type_string = dt; /* output header */ - - /* total byte size(before encode) */ - int size = len * ::icvCalcStructSize(dt, 0); - - std::string buffer = make_base64_header(size, dt); + std::string buffer = make_base64_header(dt); const uchar * beg = reinterpret_cast(buffer.data()); const uchar * end = beg + buffer.size(); - emitter.write(beg, end); - } + emitter->write(beg, end); + } else if ( data_type_string != dt ) + CV_Error( CV_StsBadArg, "\'dt\' does not match." ); +} - void write(const void* _data, int len) - { - CV_Assert(len >= 0); - CV_Assert(remaining_data_length >= static_cast(len)); - remaining_data_length -= static_cast(len); - - RawDataToBinaryConvertor convertor(_data, len, data_type_string); - emitter.write(convertor); - } - - template inline - void write(_to_binary_convertor_t & convertor, int data_length_of_convertor) - { - CV_Assert(data_length_of_convertor >= 0); - CV_Assert(remaining_data_length >= static_cast(data_length_of_convertor)); - remaining_data_length -= static_cast(data_length_of_convertor); - - emitter.write(convertor); - } - - ~Base64Writer() - { - CV_Assert(remaining_data_length == 0U); - emitter.flush(); - cvEndWriteStruct(file_storage); - icvFSFlush(file_storage); - } - -private: - - ::CvFileStorage * file_storage; - Base64ContextEmitter emitter; - size_t remaining_data_length; - const char* data_type_string; -}; void base64::make_seq(void * binary, int elem_cnt, const char * dt, ::CvSeq & seq) { @@ -7009,51 +7318,23 @@ void base64::make_seq(void * binary, int elem_cnt, const char * dt, ::CvSeq & se } } -void base64::cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt) +void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) { CV_Assert(fs); CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer == 0); - fs->base64_writer = new Base64Writer(fs, name, len, dt); -} -void base64::cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len) -{ - CV_Assert(fs); - CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer != 0); - fs->base64_writer->write(_data, len); -} + check_if_write_struct_is_delayed( fs, true ); -void base64::cvEndWriteRawData_Base64(::CvFileStorage * fs) -{ - CV_Assert(fs); - CV_CHECK_OUTPUT_FILE_STORAGE(fs); - CV_Assert(fs->base64_writer != 0); - delete fs->base64_writer; - fs->base64_writer = 0; -} - -void base64::cvWriteRawData_Base64(::cv::FileStorage & fs, const void* _data, int len, const char* dt) -{ - cvStartWriteStruct(*fs, fs.elname.c_str(), CV_NODE_SEQ, "binary"); + if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) { - Base64ContextEmitter emitter(*fs); - { /* header */ - /* total byte size(before encode) */ - int size = len * ::icvCalcStructSize(dt, 0); - std::string buffer = make_base64_header(size, dt); - const uchar * beg = reinterpret_cast(buffer.data()); - const uchar * end = beg + buffer.size(); - - emitter.write(beg, end); - } - { /* body */ - RawDataToBinaryConvertor convert(_data, len, dt); - emitter.write(convert); - } + switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); } - cvEndWriteStruct(*fs); + else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::InUse ) + { + CV_Error( CV_StsError, "Base64 should not be used at present." ); + } + + fs->base64_writer->write(_data, len, dt); } void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Mat const & mat) @@ -7064,31 +7345,30 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma { /* [1]output other attr */ if (mat.dims <= 2) { - cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT); + ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT); - cvWriteInt(fs, "rows", mat.rows ); - cvWriteInt(fs, "cols", mat.cols ); + ::cvWriteInt(fs, "rows", mat.rows ); + ::cvWriteInt(fs, "cols", mat.cols ); } else { - cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND); + ::cvStartWriteStruct(fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND); - cvStartWriteStruct(fs, "sizes", CV_NODE_SEQ | CV_NODE_FLOW); - cvWriteRawData(fs, mat.size.p, mat.dims, "i"); - cvEndWriteStruct(fs); + ::cvStartWriteStruct(fs, "sizes", CV_NODE_SEQ | CV_NODE_FLOW); + ::cvWriteRawData(fs, mat.size.p, mat.dims, "i"); + ::cvEndWriteStruct(fs); } - cvWriteString(fs, "dt", ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt ), 0 ); + ::cvWriteString(fs, "dt", ::icvEncodeFormat(CV_MAT_TYPE(mat.type()), dt ), 0 ); } { /* [2]deal with matrix's data */ - int len = static_cast(mat.total()); MatToBinaryConvertor convertor(mat); - cvStartWriteRawData_Base64(fs, "data", len, dt); - fs->base64_writer->write(convertor, len); - cvEndWriteRawData_Base64(fs); + ::cvStartWriteStruct(fs, "data", CV_NODE_SEQ, "binary"); + fs->base64_writer->write(convertor, dt); + ::cvEndWriteStruct(fs); } { /* [3]output end */ - cvEndWriteStruct(fs); + ::cvEndWriteStruct(fs); } } @@ -7096,36 +7376,21 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -namespace cv +CV_IMPL void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) { - void cvWriteMat_Base64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) - { - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); - } - - void cvWriteMatND_Base64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) - { - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); - } - - void cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt) - { - ::base64::cvStartWriteRawData_Base64(fs, name, len, dt); - } - - void cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len) - { - ::base64::cvWriteRawData_Base64(fs, _data, len); - } - - void cvEndWriteRawData_Base64(::CvFileStorage * fs) - { - ::base64::cvEndWriteRawData_Base64(fs); - } - + ::cv::Mat holder = ::cv::cvarrToMat(mat); + ::base64::cvWriteMat_Base64(fs, name, holder); } +CV_IMPL void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) +{ + ::cv::Mat holder = ::cv::cvarrToMat(mat); + ::base64::cvWriteMat_Base64(fs, name, holder); +} + +CV_IMPL void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) +{ + ::base64::cvWriteRawDataBase64(fs, _data, len, dt); +} /* End of file. */ diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index f2c53dc964..1f7191a669 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -593,150 +593,3 @@ TEST(Core_InputOutput, FileStorageSpaces) ASSERT_STREQ(values[i].c_str(), valuesRead[i].c_str()); } } - -TEST(Core_InputOutput, filestorage_yml_compatibility) -{ - // TODO: -} - -class CV_Base64IOTest : public cvtest::BaseTest -{ -private: - std::string file_name; - - struct data_t - { - uchar u1, u2; - int i1, i2, i3; - double d1, d2; - int i4; - }; - -public: - CV_Base64IOTest(std::string const & test_file_name) - : file_name(test_file_name) {} - ~CV_Base64IOTest() {} -protected: - void run(int) - { - try - { - std::vector rawdata; - - cv::Mat _em_out, _em_in; - cv::Mat _2d_out, _2d_in; - cv::Mat _nd_out, _nd_in; - - { /* init */ - - /* normal mat */ - _2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U)); - for (int i = 0; i < _2d_out.rows; ++i) - for (int j = 0; j < _2d_out.cols; ++j) - _2d_out.at(i, j)[1] = (i + j) % 256; - - /* 4d mat */ - const int Size[] = {4, 4, 4, 4}; - cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444)); - const cv::Range ranges[] = { - cv::Range(0, 2), - cv::Range(0, 2), - cv::Range(1, 2), - cv::Range(0, 2) }; - _nd_out = _4d(ranges); - - /* raw data */ - for (int i = 0; i < 1000; i++) { - data_t tmp; - tmp.u1 = 1; - tmp.u2 = 2; - tmp.i1 = 1; - tmp.i2 = 2; - tmp.i3 = 3; - tmp.d1 = 0.1; - tmp.d2 = 0.2; - tmp.i4 = i; - rawdata.push_back(tmp); - } - } - - { /* write */ - cv::FileStorage fs(file_name, cv::FileStorage::WRITE); - CvMat holder = _2d_out; - cv::cvWriteMat_Base64(*fs, "normal_2d_mat", &holder); - CvMatND holder_nd = _nd_out; - cv::cvWriteMatND_Base64(*fs, "normal_nd_mat", &holder_nd); - holder = _em_out; - cv::cvWriteMat_Base64(*fs, "empty_2d_mat", &holder); - - cv::cvStartWriteRawData_Base64(*fs, "rawdata", static_cast(rawdata.size()), "2u3i2di"); - for (int i = 0; i < 10; i++) - cv::cvWriteRawData_Base64(*fs, rawdata.data() + i * 100, 100); - cv::cvEndWriteRawData_Base64(*fs); - - fs.release(); - } - - { /* read */ - cv::FileStorage fs(file_name, cv::FileStorage::READ); - - /* mat */ - fs["empty_2d_mat"] >> _em_in; - fs["normal_2d_mat"] >> _2d_in; - fs["normal_nd_mat"] >> _nd_in; - - /* raw data */ - std::vector(1000).swap(rawdata); - cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), "2u3i2di"); - - fs.release(); - } - - for (int i = 0; i < 1000; i++) { - // TODO: Solve this bug in `cvReadRawData` - //EXPECT_EQ(rawdata[i].u1, 1); - //EXPECT_EQ(rawdata[i].u2, 2); - //EXPECT_EQ(rawdata[i].i1, 1); - //EXPECT_EQ(rawdata[i].i2, 2); - //EXPECT_EQ(rawdata[i].i3, 3); - //EXPECT_EQ(rawdata[i].d1, 0.1); - //EXPECT_EQ(rawdata[i].d2, 0.2); - //EXPECT_EQ(rawdata[i].i4, i); - } - - EXPECT_EQ(_em_in.rows , _em_out.rows); - EXPECT_EQ(_em_in.cols , _em_out.cols); - EXPECT_EQ(_em_in.dims , _em_out.dims); - EXPECT_EQ(_em_in.depth(), _em_out.depth()); - EXPECT_TRUE(_em_in.empty()); - - EXPECT_EQ(_2d_in.rows , _2d_in.rows); - EXPECT_EQ(_2d_in.cols , _2d_in.cols); - EXPECT_EQ(_2d_in.dims , _2d_in.dims); - EXPECT_EQ(_2d_in.depth(), _2d_in.depth()); - for(int i = 0; i < _2d_in.rows; ++i) - for (int j = 0; j < _2d_in.cols; ++j) - EXPECT_EQ(_2d_in.at(i, j), _2d_out.at(i, j)); - - EXPECT_EQ(_nd_in.rows , _nd_in.rows); - EXPECT_EQ(_nd_in.cols , _nd_in.cols); - EXPECT_EQ(_nd_in.dims , _nd_in.dims); - EXPECT_EQ(_nd_in.depth(), _nd_in.depth()); - EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0); - } - catch(...) - { - ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); - } - } -}; - -TEST(Core_InputOutput, filestorage_yml_base64) -{ - CV_Base64IOTest test("base64_test_tmp_file.yml"); test.safe_run(); -} - -TEST(Core_InputOutput, filestorage_xml_base64) -{ - CV_Base64IOTest test("base64_test_tmp_file.xml"); test.safe_run(); -} diff --git a/modules/core/test/test_io_base64.cpp b/modules/core/test/test_io_base64.cpp new file mode 100644 index 0000000000..d619106eae --- /dev/null +++ b/modules/core/test/test_io_base64.cpp @@ -0,0 +1,270 @@ +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; + +struct data_t +{ + typedef uchar u; + typedef char b; + typedef ushort w; + typedef short s; + typedef int i; + typedef float f; + typedef double d; + + u u1 ;u u2 ; i i1 ; + i i2 ;i i3 ; + d d1 ; + d d2 ; + i i4 ; + + static inline const char * signature() { return "2u3i2di"; } +}; + + +TEST(Core_InputOutput_Base64, basic) +{ + char const * filenames[] = { + "core_io_base64_basic_test.yml", + "core_io_base64_basic_test.xml", + 0 + }; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + std::vector rawdata; + + cv::Mat _em_out, _em_in; + cv::Mat _2d_out, _2d_in; + cv::Mat _nd_out, _nd_in; + cv::Mat _rd_out(64, 64, CV_64FC1), _rd_in; + + { /* init */ + + /* a normal mat */ + _2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U)); + for (int i = 0; i < _2d_out.rows; ++i) + for (int j = 0; j < _2d_out.cols; ++j) + _2d_out.at(i, j)[1] = (i + j) % 256; + + /* a 4d mat */ + const int Size[] = {4, 4, 4, 4}; + cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444)); + const cv::Range ranges[] = { + cv::Range(0, 2), + cv::Range(0, 2), + cv::Range(1, 2), + cv::Range(0, 2) }; + _nd_out = _4d(ranges); + + /* a random mat */ + cv::randu(_rd_out, cv::Scalar(0.0), cv::Scalar(1.0)); + + /* raw data */ + for (int i = 0; i < 1000; i++) { + data_t tmp; + tmp.u1 = 1; + tmp.u2 = 2; + tmp.i1 = 1; + tmp.i2 = 2; + tmp.i3 = 3; + tmp.d1 = 0.1; + tmp.d2 = 0.2; + tmp.i4 = i; + rawdata.push_back(tmp); + } + } + + { /* write */ + cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64); + fs << "normal_2d_mat" << _2d_out; + fs << "normal_nd_mat" << _nd_out; + fs << "empty_2d_mat" << _em_out; + fs << "random_mat" << _rd_out; + + cvStartWriteStruct( *fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary" ); + for (int i = 0; i < 10; i++) + cvWriteRawDataBase64(*fs, rawdata.data() + i * 100, 100, data_t::signature()); + cvEndWriteStruct( *fs ); + + fs.release(); + } + + { /* read */ + cv::FileStorage fs(name, cv::FileStorage::READ); + + /* mat */ + fs["empty_2d_mat"] >> _em_in; + fs["normal_2d_mat"] >> _2d_in; + fs["normal_nd_mat"] >> _nd_in; + fs["random_mat"] >> _rd_in; + + /* raw data */ + std::vector(1000).swap(rawdata); + cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature()); + + fs.release(); + } + + for (int i = 0; i < 1000; i++) { + // TODO: Solve this bug in `cvReadRawData` + //EXPECT_EQ(rawdata[i].u1, 1); + //EXPECT_EQ(rawdata[i].u2, 2); + //EXPECT_EQ(rawdata[i].i1, 1); + //EXPECT_EQ(rawdata[i].i2, 2); + //EXPECT_EQ(rawdata[i].i3, 3); + //EXPECT_EQ(rawdata[i].d1, 0.1); + //EXPECT_EQ(rawdata[i].d2, 0.2); + //EXPECT_EQ(rawdata[i].i4, i); + } + + EXPECT_EQ(_em_in.rows , _em_out.rows); + EXPECT_EQ(_em_in.cols , _em_out.cols); + EXPECT_EQ(_em_in.dims , _em_out.dims); + EXPECT_EQ(_em_in.depth(), _em_out.depth()); + EXPECT_TRUE(_em_in.empty()); + + EXPECT_EQ(_2d_in.rows , _2d_out.rows); + EXPECT_EQ(_2d_in.cols , _2d_out.cols); + EXPECT_EQ(_2d_in.dims , _2d_out.dims); + EXPECT_EQ(_2d_in.depth(), _2d_out.depth()); + for(int i = 0; i < _2d_out.rows; ++i) + for (int j = 0; j < _2d_out.cols; ++j) + EXPECT_EQ(_2d_in.at(i, j), _2d_out.at(i, j)); + + EXPECT_EQ(_nd_in.rows , _nd_out.rows); + EXPECT_EQ(_nd_in.cols , _nd_out.cols); + EXPECT_EQ(_nd_in.dims , _nd_out.dims); + EXPECT_EQ(_nd_in.depth(), _nd_out.depth()); + EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0); + + EXPECT_EQ(_rd_in.rows , _rd_out.rows); + EXPECT_EQ(_rd_in.cols , _rd_out.cols); + EXPECT_EQ(_rd_in.dims , _rd_out.dims); + EXPECT_EQ(_rd_in.depth(), _rd_out.depth()); + EXPECT_EQ(cv::countNonZero(cv::mean(_rd_in != _rd_out)), 0); + + remove(name); + } +} + +TEST(Core_InputOutput_Base64, valid) +{ + char const * filenames[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + "core_io_base64_other_test.yml?base64", + "core_io_base64_other_test.xml?base64", + 0 + }; + char const * real_name[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + 0 + }; + + std::vector rawdata(10, static_cast(0x00010203)); + cv::String str_out = "test_string"; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + EXPECT_NO_THROW( + { + cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64); + + cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + for (int i = 0; i < 10; i++) + cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(*fs); + cvWriteString(*fs, 0, str_out.c_str(), 1); + cvEndWriteStruct(*fs); + + fs.release(); + }); + + { + cv::FileStorage fs(name, cv::FileStorage::READ); + std::vector data_in(rawdata.size()); + fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size()); + EXPECT_TRUE(fs["manydata"][0].isSeq()); + EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin())); + cv::String str_in; + fs["manydata"][1] >> str_in; + EXPECT_TRUE(fs["manydata"][1].isString()); + EXPECT_EQ(str_in, str_out); + fs.release(); + } + + EXPECT_NO_THROW( + { + cv::FileStorage fs(name, cv::FileStorage::WRITE); + + cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); + cvWriteString(*fs, 0, str_out.c_str(), 1); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary"); + for (int i = 0; i < 10; i++) + cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvEndWriteStruct(*fs); + cvEndWriteStruct(*fs); + + fs.release(); + }); + + { + cv::FileStorage fs(name, cv::FileStorage::READ); + cv::String str_in; + fs["manydata"][0] >> str_in; + EXPECT_TRUE(fs["manydata"][0].isString()); + EXPECT_EQ(str_in, str_out); + std::vector data_in(rawdata.size()); + fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size()); + EXPECT_TRUE(fs["manydata"][1].isSeq()); + EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin())); + fs.release(); + } + + remove(real_name[ptr - filenames]); + } +} + +TEST(Core_InputOutput_Base64, invalid) +{ + char const * filenames[] = { + "core_io_base64_other_test.yml", + "core_io_base64_other_test.xml", + 0 + }; + + for (char const ** ptr = filenames; *ptr; ptr++) + { + char const * name = *ptr; + + EXPECT_ANY_THROW({ + cv::FileStorage fs(name, cv::FileStorage::WRITE); + cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ, "binary"); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + }); + + EXPECT_ANY_THROW({ + cv::FileStorage fs(name, cv::FileStorage::WRITE); + cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ); + cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); + cvWriteRawDataBase64(*fs, name, 1, "u"); + }); + + remove(name); + } +} + +TEST(Core_InputOutput_Base64, TODO_compatibility) +{ + // TODO: +} diff --git a/modules/ml/test/test_save_load.cpp b/modules/ml/test/test_save_load.cpp index d127471cc9..7c2a7c4a6c 100644 --- a/modules/ml/test/test_save_load.cpp +++ b/modules/ml/test/test_save_load.cpp @@ -65,11 +65,11 @@ int CV_SLMLTest::run_test_case( int testCaseIdx ) { get_test_error( testCaseIdx, &test_resps1 ); fname1 = tempfile(".yml.gz"); - save( fname1.c_str() ); + save( (fname1 + "?base64").c_str() ); load( fname1.c_str() ); get_test_error( testCaseIdx, &test_resps2 ); fname2 = tempfile(".yml.gz"); - save( fname2.c_str() ); + save( (fname2 + "?base64").c_str() ); } else ts->printf( cvtest::TS::LOG, "model can not be trained" ); @@ -280,7 +280,7 @@ TEST(DISABLED_ML_SVM, linear_save_load) svm1 = Algorithm::load("SVM45_X_38-1.xml"); svm2 = Algorithm::load("SVM45_X_38-2.xml"); string tname = tempfile("a.xml"); - svm2->save(tname); + svm2->save(tname + "?base64"); svm3 = Algorithm::load(tname); ASSERT_EQ(svm1->getVarCount(), svm2->getVarCount()); From 0823ec0ef04ffb39ba933aeafce78b2a1e944263 Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 16:11:20 +0800 Subject: [PATCH 072/153] modified performance test For faster test --- modules/core/perf/perf_io_base64.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index 693c1cc132..339d891008 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -13,6 +13,7 @@ typedef TestBaseWithParam Size_Mat_StrType; #define MAT_TYPES CV_8UC1, CV_32FC1 #define FILE_EXTENSION String(".xml"), String(".yml") + PERF_TEST_P(Size_Mat_StrType, fs_text, testing::Combine(testing::Values(MAT_SIZES), testing::Values(MAT_TYPES), @@ -31,7 +32,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, cv::String file_name = cv::tempfile(ext.c_str()); cv::String key = "test_mat"; - TEST_CYCLE_MULTIRUN(4) + TEST_CYCLE_MULTIRUN(2) { { FileStorage fs(file_name, cv::FileStorage::WRITE); @@ -47,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + SANITY_CHECK(dst); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -67,7 +68,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, cv::String key = "test_mat"; declare.in(src, WARMUP_RNG).out(dst); - TEST_CYCLE_MULTIRUN(4) + TEST_CYCLE_MULTIRUN(2) { { FileStorage fs(file_name, cv::FileStorage::WRITE_BASE64); @@ -82,5 +83,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + SANITY_CHECK(dst); } From 87ae4e0564e35fc677e86130eeddd39124b06f3c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 14 Jul 2016 16:36:57 +0300 Subject: [PATCH 073/153] fixed clone of empty matrix --- modules/core/src/array.cpp | 7 ++++--- modules/core/src/copy.cpp | 6 ------ modules/core/src/persistence.cpp | 2 -- modules/core/test/test_io.cpp | 1 - modules/core/test/test_mat.cpp | 8 ++++++++ 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/core/src/array.cpp b/modules/core/src/array.cpp index 1beb6bf144..5eacb0eb3f 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -115,12 +115,13 @@ cvCreateMatHeader( int rows, int cols, int type ) { type = CV_MAT_TYPE(type); - if( rows < 0 || cols <= 0 ) + if( rows < 0 || cols < 0 ) CV_Error( CV_StsBadSize, "Non-positive width or height" ); - int min_step = CV_ELEM_SIZE(type)*cols; + int min_step = CV_ELEM_SIZE(type); if( min_step <= 0 ) CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" ); + min_step *= cols; CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr)); @@ -148,7 +149,7 @@ cvInitMatHeader( CvMat* arr, int rows, int cols, if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX ) CV_Error( CV_BadNumChannels, "" ); - if( rows < 0 || cols <= 0 ) + if( rows < 0 || cols < 0 ) CV_Error( CV_StsBadSize, "Non-positive cols or rows" ); type = CV_MAT_TYPE( type ); diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 67bf15348c..f2201e66fe 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -259,12 +259,6 @@ void Mat::copyTo( OutputArray _dst ) const return; } - if( empty() ) - { - _dst.release(); - return; - } - if( _dst.isUMat() ) { _dst.create( dims, size.p, type() ); diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 4d99a4a275..f39cf044d5 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -3909,8 +3909,6 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node ) mat = cvCreateMat( rows, cols, elem_type ); cvReadRawData( fs, data, mat->data.ptr, dt ); } - else if( rows == 0 && cols == 0 ) - mat = cvCreateMatHeader( 0, 1, elem_type ); else mat = cvCreateMatHeader( rows, cols, elem_type ); diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index f2c53dc964..51a9a1b8ec 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -706,7 +706,6 @@ protected: EXPECT_EQ(_em_in.rows , _em_out.rows); EXPECT_EQ(_em_in.cols , _em_out.cols); - EXPECT_EQ(_em_in.dims , _em_out.dims); EXPECT_EQ(_em_in.depth(), _em_out.depth()); EXPECT_TRUE(_em_in.empty()); diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 95e4c055d7..5abcc2a5b9 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1538,3 +1538,11 @@ TEST(Mat, push_back_vector) ASSERT_EQ(6, result.rows); } + +TEST(Mat, regression_5917_clone_empty) +{ + Mat cloned; + Mat_ source(5, 0); + + ASSERT_NO_THROW(cloned = source.clone()); +} From 5ee61219c82110fb6e107f5962de8cf7414a517c Mon Sep 17 00:00:00 2001 From: catree Date: Sun, 17 Jul 2016 07:53:12 +0200 Subject: [PATCH 074/153] Add bib reference for overall hitrate and max false alarm rate formulas in train cascade tutorial. Remove useless backslash. --- doc/opencv.bib | 12 +++++++++++- doc/tutorials/objdetect/traincascade.markdown | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/opencv.bib b/doc/opencv.bib index 58ede18322..dea93f8b1f 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -750,7 +750,7 @@ organization = {ACM} } @INPROCEEDINGS{Viola01, - author = {Viola, Paul and Jones, Michael}, + author = {Viola, Paul and Jones, Michael J.}, title = {Rapid object detection using a boosted cascade of simple features}, booktitle = {Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on}, year = {2001}, @@ -758,6 +758,16 @@ volume = {1}, organization = {IEEE} } +@ARTICLE{Viola04, + author = {Viola, Paul and Jones, Michael J.}, + title = {Robust real-time face detection}, + journal = {International Journal of Computer Vision}, + year = {2004}, + volume = {57}, + number = {2}, + pages = {137--154}, + publisher = {Kluwer Academic Publishers} +} @INPROCEEDINGS{WJ10, author = {Xu, Wei and Mulligan, Jane}, title = {Performance evaluation of color correction approaches for automatic multi-view image and video stitching}, diff --git a/doc/tutorials/objdetect/traincascade.markdown b/doc/tutorials/objdetect/traincascade.markdown index 3e7db48284..12f7adde77 100644 --- a/doc/tutorials/objdetect/traincascade.markdown +++ b/doc/tutorials/objdetect/traincascade.markdown @@ -288,12 +288,12 @@ Command line arguments of opencv_traincascade application grouped by purposes: - -minHitRate \ Minimal desired hit rate for each stage of the classifier. Overall hit rate may be estimated - as (min_hit_rate\^number_of_stages). + as (min_hit_rate ^ number_of_stages), @cite Viola04 §4.1. - -maxFalseAlarmRate \ Maximal desired false alarm rate for each stage of the classifier. Overall false alarm rate - may be estimated as (max_false_alarm_rate\^number_of_stages). + may be estimated as (max_false_alarm_rate ^ number_of_stages), @cite Viola04 §4.1. - -weightTrimRate \ From d5179b8218336c9774d4176ef7668a4fbebf9b8a Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 19 Jul 2016 18:29:37 +0900 Subject: [PATCH 075/153] let the test Video_AccSquared.accuracy pass on linux x64 debug --- cmake/OpenCVCompilerOptions.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index db4b239f0b..d0c28ab0fb 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -201,9 +201,6 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_extra_compiler_option(-mpopcnt) endif() endif() - if((X86 OR X86_64) AND NOT MSVC AND NOT APPLE) - add_extra_compiler_option(-mf16c) - endif((X86 OR X86_64) AND NOT MSVC AND NOT APPLE) endif(NOT MINGW) if(X86 OR X86_64) From 2dec662ebf29e96499aff5ff10451889f15bbb56 Mon Sep 17 00:00:00 2001 From: kurenai Date: Tue, 19 Jul 2016 18:05:07 +0800 Subject: [PATCH 076/153] Fix error when compiling with clang --- 3rdparty/carotene/src/resize.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3rdparty/carotene/src/resize.cpp b/3rdparty/carotene/src/resize.cpp index 3a80d472df..184deb1205 100644 --- a/3rdparty/carotene/src/resize.cpp +++ b/3rdparty/carotene/src/resize.cpp @@ -432,7 +432,7 @@ inline void resizeAreaRounding(const Size2D &ssize, const Size2D &dsize, vSum = vaddq_u16(vSum, vaddl_u8(vLane4.val[0], vLane4.val[1])); vSum = vaddq_u16(vSum, vaddl_u8(vLane4.val[2], vLane4.val[3])); - vst1_u8(dst_row + dj, areaDownsamplingDivision(vSum)); + vst1_u8(dst_row + dj, (areaDownsamplingDivision(vSum))); } for ( ; dj < dsize.width; ++dj, sj += 4) @@ -706,7 +706,7 @@ inline void resizeAreaRounding(const Size2D &ssize, const Size2D &dsize, uint16x8_t v_sum = vcombine_u16(vadd_u16(vget_low_u16(v_sum0), vget_high_u16(v_sum0)), vadd_u16(vget_low_u16(v_sum1), vget_high_u16(v_sum1))); - vst1_u8(dst_row + dj, areaDownsamplingDivision(v_sum)); + vst1_u8(dst_row + dj, (areaDownsamplingDivision(v_sum))); } for (size_t dwidth = dsize.width << 2; dj < dwidth; dj += 4, sj += 16) From 78ca5ddd45a25781f931125e2eebf168178b0d2b Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 19:56:57 +0800 Subject: [PATCH 077/153] solve errors and warnings --- modules/core/include/opencv2/core/core_c.h | 2 +- modules/core/perf/perf_io_base64.cpp | 4 +- modules/core/src/persistence.cpp | 146 ++++++++++++--------- modules/core/test/test_io_base64.cpp | 4 +- 4 files changed, 86 insertions(+), 70 deletions(-) diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index 94ba1fc034..ecfc62aceb 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -2236,7 +2236,7 @@ and @param len Number of the array elements to write @param dt Specification of each array element, see @ref format_spec "format specification" */ -CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* _data, +CVAPI(void) cvWriteRawDataBase64( CvFileStorage* fs, const void* src, int len, const char* dt ); /** @brief Returns a unique pointer for a given name. diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index 339d891008..cf292c5478 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -48,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst); + SANITY_CHECK(dst, 1); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,5 +83,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst); + SANITY_CHECK(dst, 1); } diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 6eb3b0c75a..781117323b 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -183,7 +183,17 @@ typedef struct CvXMLStackRecord } CvXMLStackRecord; -namespace base64 { class Base64Writer; } +namespace base64 +{ + class Base64Writer; + + enum Base64State + { + Uncertain, + NotUse, + InUse, + }; +} #define CV_XML_OPENING_TAG 1 #define CV_XML_CLOSING_TAG 2 @@ -244,11 +254,7 @@ typedef struct CvFileStorage base64::Base64Writer * base64_writer; bool is_default_using_base64; - enum Base64State { - Uncertain, - NotUse, - InUse, - } state_of_writing_base64; /**< used in WriteRawData only */ + base64::Base64State state_of_writing_base64; /**< used in WriteRawData only */ bool is_write_struct_delayed; char* delayed_struct_key; @@ -339,7 +345,6 @@ namespace base64 private: - ::CvFileStorage * file_storage; Base64ContextEmitter * emitter; std::string data_type_string; }; @@ -1061,10 +1066,14 @@ static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr ) static std::vector analyze_file_name( std::string const & file_name ) { + static const char not_file_name = '\n'; static const char parameter_begin = '?'; static const char parameter_separator = '&'; std::vector result; + if ( file_name.find(not_file_name, 0U) != std::string::npos ) + return result; + size_t beg = file_name.find_last_of(parameter_begin); size_t end = file_name.size(); result.push_back(file_name.substr(0U, beg)); @@ -1087,7 +1096,7 @@ static std::vector analyze_file_name( std::string const & file_name return result; } -static bool is_param_exist( std::vector & const params, std::string & const param ) +static bool is_param_exist( const std::vector & params, const std::string & param ) { if ( params.size() < 2U ) return false; @@ -1095,7 +1104,7 @@ static bool is_param_exist( std::vector & const params, std::string return std::find(params.begin(), params.end(), param) != params.end(); } -static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64State state ) +static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state ) { const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; @@ -1103,30 +1112,30 @@ static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64Stat /* like a finite state machine */ switch (fs->state_of_writing_base64) { - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: switch (state) { - case CvFileStorage::Base64State::InUse: + case base64::Base64State::InUse: CV_DbgAssert( fs->base64_writer == 0 ); fs->base64_writer = new base64::Base64Writer( fs ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: break; - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::NotUse: break; default: CV_Error( CV_StsError, err_unkonwn_state ); break; } break; - case CvFileStorage::Base64State::InUse: + case base64::Base64State::InUse: switch (state) { - case CvFileStorage::Base64State::InUse: - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::InUse: + case base64::Base64State::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: delete fs->base64_writer; fs->base64_writer = 0; break; @@ -1135,14 +1144,14 @@ static void switch_to_Base64_state( CvFileStorage* fs, CvFileStorage::Base64Stat break; } break; - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::NotUse: switch (state) { - case CvFileStorage::Base64State::InUse: - case CvFileStorage::Base64State::NotUse: + case base64::Base64State::InUse: + case base64::Base64State::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case CvFileStorage::Base64State::Uncertain: + case base64::Base64State::Uncertain: break; default: CV_Error( CV_StsError, err_unkonwn_state ); @@ -1191,16 +1200,16 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ if ( change_type_to_base64 ) { fs->start_write_struct( fs, struct_key, struct_flags, "binary"); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } else { fs->start_write_struct( fs, struct_key, struct_flags, type_name); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } delete struct_key; @@ -1351,7 +1360,9 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN /* buffer for decoded data(exclude header) */ std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); - int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + int total_byte_size = static_cast( + base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ) + ); { base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); @@ -1830,11 +1841,11 @@ static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) { CV_Error( CV_StsError, "At present, output Base64 data only." ); } @@ -2305,7 +2316,9 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) /* alloc buffer for all decoded data(include header) */ std::vector binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) ); - int total_byte_size = base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ); + int total_byte_size = static_cast( + base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false ) + ); { base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() ); const uchar * buffer_beg = reinterpret_cast( base64_buffer.data() ); @@ -2980,11 +2993,11 @@ static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) { CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); } @@ -3206,14 +3219,18 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const bool write_base64 = write_mode && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; - const char * filename = 0; + const char * filename = query; - std::vector params = analyze_file_name( query ); - if ( !params.empty() ) - filename = params.begin()->c_str(); + std::vector params; + if ( !mem ) + { + params = analyze_file_name( query ); + if ( !params.empty() ) + filename = params.begin()->c_str(); - if (write_base64 == false && is_param_exist( params, std::string("base64") ) ) - write_base64 = true; + if ( write_base64 == false && is_param_exist( params, "base64" ) ) + write_base64 = true; + } if( !filename || filename[0] == '\0' ) { @@ -3317,7 +3334,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->base64_writer = 0; fs->is_default_using_base64 = write_base64; - fs->state_of_writing_base64 = CvFileStorage::Base64State::Uncertain; + fs->state_of_writing_base64 = base64::Base64State::Uncertain; fs->is_write_struct_delayed = false; fs->delayed_struct_key = 0; @@ -3499,10 +3516,10 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, { CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::NotUse ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 == base64::Base64State::NotUse ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain && CV_NODE_IS_SEQ(struct_flags) && @@ -3519,26 +3536,26 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, /* Must output Base64 data */ if ( !CV_NODE_IS_SEQ(struct_flags) ) CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); - else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } else { /* Won't output Base64 data */ - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } } @@ -3549,8 +3566,8 @@ cvEndWriteStruct( CvFileStorage* fs ) CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::Uncertain ) - switch_to_Base64_state( fs, CvFileStorage::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + switch_to_Base64_state( fs, base64::Base64State::Uncertain ); fs->end_write_struct( fs ); } @@ -3730,14 +3747,14 @@ CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { if (fs->is_default_using_base64 || - fs->state_of_writing_base64 == CvFileStorage::Base64State::InUse ) + fs->state_of_writing_base64 == base64::Base64State::InUse ) { base64::cvWriteRawDataBase64( fs, _data, len, dt ); return; } - else if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::Base64State::NotUse ); } const char* data0 = (const char*)_data; @@ -7259,8 +7276,7 @@ private: base64::Base64Writer::Base64Writer(::CvFileStorage * fs) - : file_storage(fs) - , emitter(new Base64ContextEmitter(fs)) + : emitter(new Base64ContextEmitter(fs)) , data_type_string() { CV_CHECK_OUTPUT_FILE_STORAGE(fs); @@ -7325,11 +7341,11 @@ void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int le check_if_write_struct_is_delayed( fs, true ); - if ( fs->state_of_writing_base64 == CvFileStorage::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) { - switch_to_Base64_state( fs, CvFileStorage::Base64State::InUse ); + switch_to_Base64_state( fs, base64::Base64State::InUse ); } - else if ( fs->state_of_writing_base64 != CvFileStorage::Base64State::InUse ) + else if ( fs->state_of_writing_base64 != base64::Base64State::InUse ) { CV_Error( CV_StsError, "Base64 should not be used at present." ); } @@ -7376,13 +7392,13 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -CV_IMPL void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) +void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) { ::cv::Mat holder = ::cv::cvarrToMat(mat); ::base64::cvWriteMat_Base64(fs, name, holder); } -CV_IMPL void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) +void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) { ::cv::Mat holder = ::cv::cvarrToMat(mat); ::base64::cvWriteMat_Base64(fs, name, holder); diff --git a/modules/core/test/test_io_base64.cpp b/modules/core/test/test_io_base64.cpp index d619106eae..35fb18c139 100644 --- a/modules/core/test/test_io_base64.cpp +++ b/modules/core/test/test_io_base64.cpp @@ -182,7 +182,7 @@ TEST(Core_InputOutput_Base64, valid) cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ); cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW); for (int i = 0; i < 10; i++) - cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawData(*fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(*fs); cvWriteString(*fs, 0, str_out.c_str(), 1); cvEndWriteStruct(*fs); @@ -211,7 +211,7 @@ TEST(Core_InputOutput_Base64, valid) cvWriteString(*fs, 0, str_out.c_str(), 1); cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary"); for (int i = 0; i < 10; i++) - cvWriteRawData(*fs, rawdata.data(), rawdata.size(), "i"); + cvWriteRawData(*fs, rawdata.data(), static_cast(rawdata.size()), "i"); cvEndWriteStruct(*fs); cvEndWriteStruct(*fs); From cf2d6f6721704e4d8e9f410f77df2f832ce748b9 Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 21:18:41 +0800 Subject: [PATCH 078/153] solve errors and warnings Modified performance test and solve a problem caused by an enum type. --- modules/core/perf/perf_io_base64.cpp | 5 +- modules/core/src/persistence.cpp | 117 +++++++++++++-------------- 2 files changed, 57 insertions(+), 65 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index cf292c5478..a39c0cbce8 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -48,7 +48,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + EXPECT_EQ( src, dst ); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,5 +83,6 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - SANITY_CHECK(dst, 1); + + EXPECT_EQ( src, dst ); } diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 781117323b..e4fc0c6be7 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -187,12 +187,15 @@ namespace base64 { class Base64Writer; - enum Base64State + namespace fs { - Uncertain, - NotUse, - InUse, - }; + enum State + { + Uncertain, + NotUse, + InUse, + }; + } } #define CV_XML_OPENING_TAG 1 @@ -254,7 +257,7 @@ typedef struct CvFileStorage base64::Base64Writer * base64_writer; bool is_default_using_base64; - base64::Base64State state_of_writing_base64; /**< used in WriteRawData only */ + base64::fs::State state_of_writing_base64; /**< used in WriteRawData only */ bool is_write_struct_delayed; char* delayed_struct_key; @@ -1104,7 +1107,7 @@ static bool is_param_exist( const std::vector & params, const std:: return std::find(params.begin(), params.end(), param) != params.end(); } -static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state ) +static void switch_to_Base64_state( CvFileStorage* fs, base64::fs::State state ) { const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state."; const char * err_unable_to_switch = "Unexpected error, unable to switch to this state."; @@ -1112,30 +1115,30 @@ static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state /* like a finite state machine */ switch (fs->state_of_writing_base64) { - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: switch (state) { - case base64::Base64State::InUse: + case base64::fs::InUse: CV_DbgAssert( fs->base64_writer == 0 ); fs->base64_writer = new base64::Base64Writer( fs ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: break; - case base64::Base64State::NotUse: + case base64::fs::NotUse: break; default: CV_Error( CV_StsError, err_unkonwn_state ); break; } break; - case base64::Base64State::InUse: + case base64::fs::InUse: switch (state) { - case base64::Base64State::InUse: - case base64::Base64State::NotUse: + case base64::fs::InUse: + case base64::fs::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: delete fs->base64_writer; fs->base64_writer = 0; break; @@ -1144,14 +1147,14 @@ static void switch_to_Base64_state( CvFileStorage* fs, base64::Base64State state break; } break; - case base64::Base64State::NotUse: + case base64::fs::NotUse: switch (state) { - case base64::Base64State::InUse: - case base64::Base64State::NotUse: + case base64::fs::InUse: + case base64::fs::NotUse: CV_Error( CV_StsError, err_unable_to_switch ); break; - case base64::Base64State::Uncertain: + case base64::fs::Uncertain: break; default: CV_Error( CV_StsError, err_unkonwn_state ); @@ -1200,16 +1203,16 @@ static void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_typ if ( change_type_to_base64 ) { fs->start_write_struct( fs, struct_key, struct_flags, "binary"); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::InUse ); } else { fs->start_write_struct( fs, struct_key, struct_flags, type_name); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } delete struct_key; @@ -1841,11 +1844,11 @@ static void icvYMLWrite( CvFileStorage* fs, const char* key, const char* data ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } - else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::fs::InUse ) { CV_Error( CV_StsError, "At present, output Base64 data only." ); } @@ -2993,11 +2996,11 @@ static void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len ) { check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } - else if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 == base64::fs::InUse ) { CV_Error( CV_StsError, "Currently only Base64 data is allowed." ); } @@ -3334,7 +3337,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const fs->base64_writer = 0; fs->is_default_using_base64 = write_base64; - fs->state_of_writing_base64 = base64::Base64State::Uncertain; + fs->state_of_writing_base64 = base64::fs::Uncertain; fs->is_write_struct_delayed = false; fs->delayed_struct_key = 0; @@ -3516,10 +3519,10 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, { CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 == base64::Base64State::NotUse ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 == base64::fs::NotUse ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain + if ( fs->state_of_writing_base64 == base64::fs::Uncertain && CV_NODE_IS_SEQ(struct_flags) && @@ -3536,26 +3539,26 @@ cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, /* Must output Base64 data */ if ( !CV_NODE_IS_SEQ(struct_flags) ) CV_Error( CV_StsBadArg, "must set 'struct_flags |= CV_NODE_SEQ' if using Base64."); - else if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) CV_Error( CV_StsError, "function \'cvStartWriteStruct\' calls cannot be nested if using Base64."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::InUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::InUse ); } else { /* Won't output Base64 data */ - if ( fs->state_of_writing_base64 == base64::Base64State::InUse ) + if ( fs->state_of_writing_base64 == base64::fs::InUse ) CV_Error( CV_StsError, "At the end of the output Base64, `cvEndWriteStruct` is needed."); fs->start_write_struct( fs, key, struct_flags, type_name ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } } @@ -3566,8 +3569,8 @@ cvEndWriteStruct( CvFileStorage* fs ) CV_CHECK_OUTPUT_FILE_STORAGE(fs); check_if_write_struct_is_delayed( fs ); - if ( fs->state_of_writing_base64 != base64::Base64State::Uncertain ) - switch_to_Base64_state( fs, base64::Base64State::Uncertain ); + if ( fs->state_of_writing_base64 != base64::fs::Uncertain ) + switch_to_Base64_state( fs, base64::fs::Uncertain ); fs->end_write_struct( fs ); } @@ -3747,14 +3750,14 @@ CV_IMPL void cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) { if (fs->is_default_using_base64 || - fs->state_of_writing_base64 == base64::Base64State::InUse ) + fs->state_of_writing_base64 == base64::fs::InUse ) { base64::cvWriteRawDataBase64( fs, _data, len, dt ); return; } - else if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + else if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::NotUse ); + switch_to_Base64_state( fs, base64::fs::NotUse ); } const char* data0 = (const char*)_data; @@ -7341,11 +7344,11 @@ void base64::cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int le check_if_write_struct_is_delayed( fs, true ); - if ( fs->state_of_writing_base64 == base64::Base64State::Uncertain ) + if ( fs->state_of_writing_base64 == base64::fs::Uncertain ) { - switch_to_Base64_state( fs, base64::Base64State::InUse ); + switch_to_Base64_state( fs, base64::fs::InUse ); } - else if ( fs->state_of_writing_base64 != base64::Base64State::InUse ) + else if ( fs->state_of_writing_base64 != base64::fs::InUse ) { CV_Error( CV_StsError, "Base64 should not be used at present." ); } @@ -7392,18 +7395,6 @@ void base64::cvWriteMat_Base64(::CvFileStorage * fs, const char * name, ::cv::Ma * Interface ***************************************************************************/ -void cvWriteMatBase64(::CvFileStorage* fs, const char* name, const ::CvMat* mat) -{ - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); -} - -void cvWriteMatNDBase64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat) -{ - ::cv::Mat holder = ::cv::cvarrToMat(mat); - ::base64::cvWriteMat_Base64(fs, name, holder); -} - CV_IMPL void cvWriteRawDataBase64(::CvFileStorage* fs, const void* _data, int len, const char* dt) { ::base64::cvWriteRawDataBase64(fs, _data, len, dt); From 6c42ad5b90dd9e096292c63963214ddaecd4e2ba Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 19 Jul 2016 16:18:48 +0300 Subject: [PATCH 079/153] fixed typo --- modules/core/test/test_mat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 95e4c055d7..ada0ba04b6 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1392,7 +1392,7 @@ TEST(Core_SparseMat, footprint) } -// Can't fix without duty hacks or broken user code (PR #4159) +// Can't fix without dirty hacks or broken user code (PR #4159) TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat) { cv::Mat_ src_base(5, 1); @@ -1420,7 +1420,7 @@ TEST(Core_Mat_vector, copyTo_roi_column) Mat src_full(src_base); Mat src(src_full.col(0)); -#if 0 // Can't fix without duty hacks or broken user code (PR #4159) +#if 0 // Can't fix without dirty hacks or broken user code (PR #4159) OutputArray _dst(dst1); { _dst.create(src.rows, src.cols, src.type()); From d06b8c4ea9d30be7f60196cdf3c9a65f64370fa4 Mon Sep 17 00:00:00 2001 From: Sergei Nosov Date: Tue, 19 Jul 2016 17:05:30 +0300 Subject: [PATCH 080/153] add test for #6836 --- .../calib3d/test/test_cameracalibration.cpp | 104 +++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 2dad0cf222..357208dd6c 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1346,6 +1346,108 @@ void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec ///////////////////////////////// Stereo Calibration ///////////////////////////////////// +class CV_StereoCalibrationCornerTest : public cvtest::BaseTest +{ +public: + CV_StereoCalibrationCornerTest(); + ~CV_StereoCalibrationCornerTest(); + void clear(); +protected: + void run(int); +}; + +CV_StereoCalibrationCornerTest::CV_StereoCalibrationCornerTest() +{ +} + + +CV_StereoCalibrationCornerTest::~CV_StereoCalibrationCornerTest() +{ + clear(); +} + +void CV_StereoCalibrationCornerTest::clear() +{ + cvtest::BaseTest::clear(); +} + +static bool resizeCameraMatrix(const Mat &in_cm, Mat &dst_cm, double scale) +{ + if (in_cm.empty() || in_cm.cols != 3 || in_cm.rows != 3 || in_cm.type() != CV_64FC1) + return false; + dst_cm = in_cm * scale; + dst_cm.at(2, 2) = 1.0; + return true; +} + +// see https://github.com/opencv/opencv/pull/6836 for details +void CV_StereoCalibrationCornerTest::run(int) +{ + const Matx33d M1(906.7857732303256, 0.0, 1026.456125870669, + 0.0, 906.7857732303256, 540.0531577669913, + 0.0, 0.0, 1.0); + const Matx33d M2(906.782205162265, 0.0, 1014.619997352785, + 0.0, 906.782205162265, 561.9990018887295, + 0.0, 0.0, 1.0); + const Matx D1(0.0064836857220181504, 0.033880363848984636, 0.0, 0.0, -0.042996356352306114); + const Matx D2(0.023754068600491646, -0.02364619610835259, 0.0, 0.0, 0.0015014971456262652); + + const Size imageSize(2048, 1088); + const double scale = 0.25; + + const Matx33d Rot(0.999788461750194, -0.015696495349844446, -0.013291041528534329, + 0.015233019205877604, 0.999296086451901, -0.034282455101525826, + 0.01381980018141639, 0.03407274036010432, 0.9993238021218641); + const Matx31d T(-1.552005597952028, 0.0019508251875105093, -0.023335501616116062); + + // generate camera matrices for resized image rectification. + Mat srcM1(M1), srcM2(M2); + Mat rszM1, rszM2; + resizeCameraMatrix(srcM1, rszM1, scale); + resizeCameraMatrix(srcM2, rszM2, scale); + Size rszImageSize(cvRound(scale * imageSize.width), cvRound(scale * imageSize.height)); + Size srcImageSize = imageSize; + // apply stereoRectify + Mat srcR[2], srcP[2], srcQ; + Mat rszR[2], rszP[2], rszQ; + stereoRectify(srcM1, D1, srcM2, D2, srcImageSize, Rot, T, + srcR[0], srcR[1], srcP[0], srcP[1], srcQ, + CALIB_ZERO_DISPARITY, 0); + stereoRectify(rszM1, D1, rszM2, D2, rszImageSize, Rot, T, + rszR[0], rszR[1], rszP[0], rszP[1], rszQ, + CALIB_ZERO_DISPARITY, 0); + // generate remap maps + Mat srcRmap[2], rszRmap[2]; + initUndistortRectifyMap(srcM1, D1, srcR[0], srcP[0], srcImageSize, CV_32FC2, srcRmap[0], srcRmap[1]); + initUndistortRectifyMap(rszM1, D1, rszR[0], rszP[0], rszImageSize, CV_32FC2, rszRmap[0], rszRmap[1]); + + // generate source image + // it's an artificial pattern with white rect in the center + Mat image(imageSize, CV_8UC3); + image.setTo(0); + image(cv::Rect(imageSize.width / 3, imageSize.height / 3, imageSize.width / 3, imageSize.height / 3)).setTo(255); + + // perform remap-resize + Mat src_result; + remap(image, src_result, srcRmap[0], srcRmap[1], INTER_LINEAR); + resize(src_result, src_result, Size(), scale, scale, INTER_LINEAR); + // perform resize-remap + Mat rsz_result; + resize(image, rsz_result, Size(), scale, scale, INTER_LINEAR); + remap(rsz_result, rsz_result, rszRmap[0], rszRmap[1], INTER_LINEAR); + + // modifying the camera matrix with resizeCameraMatrix must yield the same + // result as calibrating the downscaled images + int cnz = countNonZero((cv::Mat(src_result - rsz_result) != 0)( + cv::Rect(src_result.cols / 3, src_result.rows / 3, + src_result.cols / 3.1, src_result.rows / 3.1))); + if (cnz) + { + ts->printf( cvtest::TS::LOG, "The camera matrix is wrong for downscaled image\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } +} + class CV_StereoCalibrationTest : public cvtest::BaseTest { public: @@ -1949,7 +2051,7 @@ TEST(Calib3d_ProjectPoints_C, accuracy) { CV_ProjectPointsTest_C test; test.saf TEST(Calib3d_ProjectPoints_CPP, regression) { CV_ProjectPointsTest_CPP test; test.safe_run(); } TEST(Calib3d_StereoCalibrate_C, regression) { CV_StereoCalibrationTest_C test; test.safe_run(); } TEST(Calib3d_StereoCalibrate_CPP, regression) { CV_StereoCalibrationTest_CPP test; test.safe_run(); } - +TEST(Calib3d_StereoCalibrateCorner, regression) { CV_StereoCalibrationCornerTest test; test.safe_run(); } TEST(Calib3d_Triangulate, accuracy) { From 27b924e99e1461ccd84f2d4a74cf306c370dc5ad Mon Sep 17 00:00:00 2001 From: MYLS Date: Tue, 19 Jul 2016 22:06:21 +0800 Subject: [PATCH 081/153] remove CHECK from performance test --- modules/core/perf/perf_io_base64.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index a39c0cbce8..f2982b2cb0 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -47,8 +47,6 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, } remove(file_name.c_str()); - - EXPECT_EQ( src, dst ); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -83,6 +81,4 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); - - EXPECT_EQ( src, dst ); } From 460b1dc2faf030c171fc2fd43ddb113bc800596e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Jul 2016 16:08:09 +0300 Subject: [PATCH 082/153] imgproc: Canny with custom gradient --- modules/imgproc/include/opencv2/imgproc.hpp | 13 +++ modules/imgproc/src/canny.cpp | 96 ++++++++++++++++----- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 9f4763d34f..ee022476f0 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1664,6 +1664,19 @@ CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false ); +/** \overload + +Finds edges in an image using the Canny algorithm with custom image gradient. + +@param dx 16-bit x derivative of input image (CV_16SC1 or CV_16SC3). +@param dy 16-bit y derivative of input image (same type as dx). +@param edges,threshold1,threshold2,L2gradient See cv::Canny + */ +CV_EXPORTS_W void Canny( InputArray dx, InputArray dy, + OutputArray edges, + double threshold1, double threshold2, + bool L2gradient = false ); + /** @brief Calculates the minimal eigenvalue of gradient matrices for corner detection. The function is similar to cornerEigenValsAndVecs but it calculates and stores only the minimal diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 53fb66bbbe..18f38284f5 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -43,6 +43,10 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#ifdef _MSC_VER +#pragma warning( disable: 4127 ) // conditional expression is constant +#endif + #if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #define USE_IPP_CANNY 1 @@ -53,6 +57,10 @@ namespace cv { + +static void CannyImpl(Mat& dx_, Mat& dy_, Mat& _dst, double low_thresh, double high_thresh, bool L2gradient); + + #ifdef HAVE_IPP static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) { @@ -585,9 +593,7 @@ private: #endif -} // namespace cv - -void cv::Canny( InputArray _src, OutputArray _dst, +void Canny( InputArray _src, OutputArray _dst, double low_thresh, double high_thresh, int aperture_size, bool L2gradient ) { @@ -683,14 +689,60 @@ while (borderPeaks.try_pop(m)) if (!m[mapstep+1]) CANNY_PUSH_SERIAL(m + mapstep + 1); } -#else +// the final pass, form the final image +const uchar* pmap = map + mapstep + 1; +uchar* pdst = dst.ptr(); +for (int i = 0; i < src.rows; i++, pmap += mapstep, pdst += dst.step) +{ + for (int j = 0; j < src.cols; j++) + pdst[j] = (uchar)-(pmap[j] >> 1); +} +#else Mat dx(src.rows, src.cols, CV_16SC(cn)); Mat dy(src.rows, src.cols, CV_16SC(cn)); Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); + CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient); +#endif +} + +void Canny( InputArray _dx, InputArray _dy, OutputArray _dst, + double low_thresh, double high_thresh, + bool L2gradient ) +{ + CV_Assert(_dx.dims() == 2); + CV_Assert(_dx.type() == CV_16SC1 || _dx.type() == CV_16SC3); + CV_Assert(_dy.type() == _dx.type()); + CV_Assert(_dx.sameSize(_dy)); + + if (low_thresh > high_thresh) + std::swap(low_thresh, high_thresh); + + const int cn = _dx.channels(); + const Size size = _dx.size(); + _dst.create(size, CV_8U); + Mat dst = _dst.getMat(); + + Mat dx = _dx.getMat(); + Mat dy = _dy.getMat(); + if (cn > 1) + { + dx = dx.clone(); + dy = dy.clone(); + } + + CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient); +} + +static void CannyImpl(Mat& dx, Mat& dy, Mat& dst, + double low_thresh, double high_thresh, bool L2gradient) +{ + const int cn = dx.channels(); + const int cols = dx.cols, rows = dx.rows; + if (L2gradient) { low_thresh = std::min(32767.0, low_thresh); @@ -702,8 +754,8 @@ while (borderPeaks.try_pop(m)) int low = cvFloor(low_thresh); int high = cvFloor(high_thresh); - ptrdiff_t mapstep = src.cols + 2; - AutoBuffer buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int)); + ptrdiff_t mapstep = cols + 2; + AutoBuffer buffer((cols+2)*(rows+2) + cn * mapstep * 3 * sizeof(int)); int* mag_buf[3]; mag_buf[0] = (int*)(uchar*)buffer; @@ -713,9 +765,9 @@ while (borderPeaks.try_pop(m)) uchar* map = (uchar*)(mag_buf[2] + mapstep*cn); memset(map, 1, mapstep); - memset(map + mapstep*(src.rows + 1), 1, mapstep); + memset(map + mapstep*(rows + 1), 1, mapstep); - int maxsize = std::max(1 << 10, src.cols * src.rows / 10); + int maxsize = std::max(1 << 10, cols * rows / 10); std::vector stack(maxsize); uchar **stack_top = &stack[0]; uchar **stack_bottom = &stack[0]; @@ -744,17 +796,17 @@ while (borderPeaks.try_pop(m)) // 0 - the pixel might belong to an edge // 1 - the pixel can not belong to an edge // 2 - the pixel does belong to an edge - for (int i = 0; i <= src.rows; i++) + for (int i = 0; i <= rows; i++) { int* _norm = mag_buf[(i > 0) + 1] + 1; - if (i < src.rows) + if (i < rows) { short* _dx = dx.ptr(i); short* _dy = dy.ptr(i); if (!L2gradient) { - int j = 0, width = src.cols * cn; + int j = 0, width = cols * cn; #if CV_SSE2 if (haveSSE2) { @@ -788,7 +840,7 @@ while (borderPeaks.try_pop(m)) } else { - int j = 0, width = src.cols * cn; + int j = 0, width = cols * cn; #if CV_SSE2 if (haveSSE2) { @@ -824,7 +876,7 @@ while (borderPeaks.try_pop(m)) if (cn > 1) { - for(int j = 0, jn = 0; j < src.cols; ++j, jn += cn) + for(int j = 0, jn = 0; j < cols; ++j, jn += cn) { int maxIdx = jn; for(int k = 1; k < cn; ++k) @@ -834,7 +886,7 @@ while (borderPeaks.try_pop(m)) _dy[j] = _dy[maxIdx]; } } - _norm[-1] = _norm[src.cols] = 0; + _norm[-1] = _norm[cols] = 0; } else memset(_norm-1, 0, /* cn* */mapstep*sizeof(int)); @@ -845,7 +897,7 @@ while (borderPeaks.try_pop(m)) continue; uchar* _map = map + mapstep*i + 1; - _map[-1] = _map[src.cols] = 1; + _map[-1] = _map[cols] = 1; int* _mag = mag_buf[1] + 1; // take the central row ptrdiff_t magstep1 = mag_buf[2] - mag_buf[1]; @@ -854,17 +906,17 @@ while (borderPeaks.try_pop(m)) const short* _x = dx.ptr(i-1); const short* _y = dy.ptr(i-1); - if ((stack_top - stack_bottom) + src.cols > maxsize) + if ((stack_top - stack_bottom) + cols > maxsize) { int sz = (int)(stack_top - stack_bottom); - maxsize = std::max(maxsize * 3/2, sz + src.cols); + maxsize = std::max(maxsize * 3/2, sz + cols); stack.resize(maxsize); stack_bottom = &stack[0]; stack_top = stack_bottom + sz; } int prev_flag = 0; - for (int j = 0; j < src.cols; j++) + for (int j = 0; j < cols; j++) { #define CANNY_SHIFT 15 const int TG22 = (int)(0.4142135623730950488016887242097*(1<> 1); } } +} // namespace cv + void cvCanny( const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size ) { From 575de89ee21f8cae9499b4305f621235591cdf5c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Jul 2016 16:34:21 +0300 Subject: [PATCH 083/153] imgproc: Canny: enable IPP & OpenCL optimization code path --- modules/imgproc/src/canny.cpp | 102 ++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 18f38284f5..5ba15a3ffe 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -62,52 +62,68 @@ static void CannyImpl(Mat& dx_, Mat& dy_, Mat& _dst, double low_thresh, double h #ifdef HAVE_IPP -static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) +template +static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, float low, float high) { #if USE_IPP_CANNY int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; + if (ippiCannyGetSize(roi, &size) < 0) + return false; + + if (!useCustomDeriv) + { #if IPP_VERSION_X100 < 900 - if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size) < 0) - return false; - if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0) - return false; + if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0) + return false; + size = std::max(size, size1); + if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0) + return false; #else - if (ippiFilterSobelNegVertBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size) < 0) - return false; - if (ippiFilterSobelHorizBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0) - return false; + if (ippiFilterSobelNegVertBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0) + return false; + size = std::max(size, size1); + if (ippiFilterSobelHorizBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0) + return false; #endif - - size = std::max(size, size1); - - if (ippiCannyGetSize(roi, &size1) < 0) - return false; - size = std::max(size, size1); + size = std::max(size, size1); + } AutoBuffer buf(size + 64); uchar* buffer = alignPtr((uchar*)buf, 32); - Mat _dx(_src.rows, _src.cols, CV_16S); - if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.ptr(), (int)_src.step, - _dx.ptr(), (int)_dx.step, roi, - ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) - return false; + Mat dx, dy; + if (!useCustomDeriv) + { + Mat _dx(_src.rows, _src.cols, CV_16S); + if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.ptr(), (int)_src.step, + _dx.ptr(), (int)_dx.step, roi, + ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) + return false; - Mat _dy(_src.rows, _src.cols, CV_16S); - if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.ptr(), (int)_src.step, - _dy.ptr(), (int)_dy.step, roi, - ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) - return false; + Mat _dy(_src.rows, _src.cols, CV_16S); + if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.ptr(), (int)_src.step, + _dy.ptr(), (int)_dy.step, roi, + ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 ) + return false; - if( ippiCanny_16s8u_C1R(_dx.ptr(), (int)_dx.step, - _dy.ptr(), (int)_dy.step, + swap(dx, _dx); + swap(dy, _dy); + } + else + { + dx = dx_; + dy = dy_; + } + + if( ippiCanny_16s8u_C1R(dx.ptr(), (int)dx.step, + dy.ptr(), (int)dy.step, _dst.ptr(), (int)_dst.step, roi, low, high, buffer) < 0 ) return false; return true; #else - CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high); + CV_UNUSED(_src); CV_UNUSED(dx_); CV_UNUSED(dy_); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high); return false; #endif } @@ -115,7 +131,8 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) #ifdef HAVE_OPENCL -static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float high_thresh, +template +static bool ocl_Canny(InputArray _src, const UMat& dx_, const UMat& dy_, OutputArray _dst, float low_thresh, float high_thresh, int aperture_size, bool L2gradient, int cn, const Size & size) { UMat map; @@ -148,7 +165,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float } int low = cvFloor(low_thresh), high = cvFloor(high_thresh); - if (aperture_size == 3 && !_src.isSubmatrix()) + if (!useCustomDeriv && + aperture_size == 3 && !_src.isSubmatrix()) { /* stage1_with_sobel: @@ -189,8 +207,16 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float Double thresholding */ UMat dx, dy; - Sobel(_src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); - Sobel(_src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); + if (!useCustomDeriv) + { + Sobel(_src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); + Sobel(_src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); + } + else + { + dx = dx_; + dy = dy_; + } ocl::Kernel without_sobel("stage1_without_sobel", ocl::imgproc::canny_oclsrc, format("-D WITHOUT_SOBEL -D cn=%d -D GRP_SIZEX=%d -D GRP_SIZEY=%d%s", @@ -617,7 +643,7 @@ void Canny( InputArray _src, OutputArray _dst, std::swap(low_thresh, high_thresh); CV_OCL_RUN(_dst.isUMat() && (cn == 1 || cn == 3), - ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size)) + ocl_Canny(_src, UMat(), UMat(), _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size)) Mat src = _src.getMat(), dst = _dst.getMat(); @@ -626,7 +652,7 @@ void Canny( InputArray _src, OutputArray _dst, return; #endif - CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, dst, (float)low_thresh, (float)high_thresh)) + CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, Mat(), Mat(), dst, (float)low_thresh, (float)high_thresh)) #ifdef HAVE_TBB @@ -723,17 +749,23 @@ void Canny( InputArray _dx, InputArray _dy, OutputArray _dst, const int cn = _dx.channels(); const Size size = _dx.size(); + + CV_OCL_RUN(_dst.isUMat(), + ocl_Canny(UMat(), _dx.getUMat(), _dy.getUMat(), _dst, (float)low_thresh, (float)high_thresh, 0, L2gradient, cn, size)) + _dst.create(size, CV_8U); Mat dst = _dst.getMat(); Mat dx = _dx.getMat(); Mat dy = _dy.getMat(); + + CV_IPP_RUN(USE_IPP_CANNY && (!L2gradient && 1 == cn), ippCanny(Mat(), dx, dy, dst, (float)low_thresh, (float)high_thresh)) + if (cn > 1) { dx = dx.clone(); dy = dy.clone(); } - CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient); } From e20a93f7d67fdf70ab19055b5e70b0c953d0175e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Jul 2016 17:08:27 +0300 Subject: [PATCH 084/153] imgproc test: Canny with custom gradient --- modules/imgproc/test/ocl/test_canny.cpp | 37 ++++++++++++++++++---- modules/imgproc/test/test_canny.cpp | 27 ++++++++++++++-- modules/ts/include/opencv2/ts/ocl_test.hpp | 4 +-- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/modules/imgproc/test/ocl/test_canny.cpp b/modules/imgproc/test/ocl/test_canny.cpp index 70e4bb1fcf..f9c724b049 100644 --- a/modules/imgproc/test/ocl/test_canny.cpp +++ b/modules/imgproc/test/ocl/test_canny.cpp @@ -54,13 +54,13 @@ namespace ocl { //////////////////////////////////////////////////////// // Canny -IMPLEMENT_PARAM_CLASS(AppertureSize, int) +IMPLEMENT_PARAM_CLASS(ApertureSize, int) IMPLEMENT_PARAM_CLASS(L2gradient, bool) IMPLEMENT_PARAM_CLASS(UseRoi, bool) -PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi) +PARAM_TEST_CASE(Canny, Channels, ApertureSize, L2gradient, UseRoi) { - int cn, apperture_size; + int cn, aperture_size; bool useL2gradient, use_roi; TEST_DECLARE_INPUT_PARAMETER(src); @@ -69,7 +69,7 @@ PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi) virtual void SetUp() { cn = GET_PARAM(0); - apperture_size = GET_PARAM(1); + aperture_size = GET_PARAM(1); useL2gradient = GET_PARAM(2); use_roi = GET_PARAM(3); } @@ -105,8 +105,31 @@ OCL_TEST_P(Canny, Accuracy) eps = 12e-3; #endif - OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, apperture_size, useL2gradient)); - OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, apperture_size, useL2gradient)); + OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); + OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); + + EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps); + EXPECT_MAT_SIMILAR(dst, udst, eps); +} + +OCL_TEST_P(Canny, AccuracyCustomGradient) +{ + generateTestData(); + + const double low_thresh = 50.0, high_thresh = 100.0; + double eps = 1e-2; +#ifdef ANDROID + if (cv::ocl::Device::getDefault().isNVidia()) + eps = 12e-3; +#endif + + OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); + OCL_ON( + UMat dx, dy; + Sobel(usrc_roi, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); + Sobel(usrc_roi, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); + cv::Canny(dx, dy, udst_roi, low_thresh, high_thresh, useL2gradient); + ); EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps); EXPECT_MAT_SIMILAR(dst, udst, eps); @@ -114,7 +137,7 @@ OCL_TEST_P(Canny, Accuracy) OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Canny, testing::Combine( testing::Values(1, 3), - testing::Values(AppertureSize(3), AppertureSize(5)), + testing::Values(ApertureSize(3), ApertureSize(5)), testing::Values(L2gradient(false), L2gradient(true)), testing::Values(UseRoi(false), UseRoi(true)))); diff --git a/modules/imgproc/test/test_canny.cpp b/modules/imgproc/test/test_canny.cpp index 15b9ea5b1c..db4a82bf9d 100644 --- a/modules/imgproc/test/test_canny.cpp +++ b/modules/imgproc/test/test_canny.cpp @@ -47,7 +47,7 @@ using namespace std; class CV_CannyTest : public cvtest::ArrayTest { public: - CV_CannyTest(); + CV_CannyTest(bool custom_deriv = false); protected: void get_test_array_types_and_sizes( int test_case_idx, vector >& sizes, vector >& types ); @@ -61,10 +61,11 @@ protected: bool use_true_gradient; double threshold1, threshold2; bool test_cpp; + bool test_custom_deriv; }; -CV_CannyTest::CV_CannyTest() +CV_CannyTest::CV_CannyTest(bool custom_deriv) { test_array[INPUT].push_back(NULL); test_array[OUTPUT].push_back(NULL); @@ -75,6 +76,7 @@ CV_CannyTest::CV_CannyTest() threshold1 = threshold2 = 0; test_cpp = false; + test_custom_deriv = custom_deriv; } @@ -99,6 +101,9 @@ void CV_CannyTest::get_test_array_types_and_sizes( int test_case_idx, use_true_gradient = cvtest::randInt(rng) % 2 != 0; test_cpp = (cvtest::randInt(rng) & 256) == 0; + + ts->printf(cvtest::TS::LOG, "Canny(size = %d x %d, aperture_size = %d, threshold1 = %g, threshold2 = %g, L2 = %s) test_cpp = %s (test case #%d)\n", + sizes[0][0].width, sizes[0][0].height, aperture_size, threshold1, threshold2, use_true_gradient ? "TRUE" : "FALSE", test_cpp ? "TRUE" : "FALSE", test_case_idx); } @@ -123,9 +128,24 @@ double CV_CannyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, void CV_CannyTest::run_func() { - if(!test_cpp) + if (test_custom_deriv) + { + cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]); + cv::Mat src = cv::cvarrToMat(test_array[INPUT][0]); + cv::Mat dx, dy; + int m = aperture_size; + Point anchor(m/2, m/2); + Mat dxkernel = cvtest::calcSobelKernel2D( 1, 0, m, 0 ); + Mat dykernel = cvtest::calcSobelKernel2D( 0, 1, m, 0 ); + cvtest::filter2D(src, dx, CV_16S, dxkernel, anchor, 0, BORDER_REPLICATE); + cvtest::filter2D(src, dy, CV_16S, dykernel, anchor, 0, BORDER_REPLICATE); + cv::Canny(dx, dy, _out, threshold1, threshold2, use_true_gradient); + } + else if(!test_cpp) + { cvCanny( test_array[INPUT][0], test_array[OUTPUT][0], threshold1, threshold2, aperture_size + (use_true_gradient ? CV_CANNY_L2_GRADIENT : 0)); + } else { cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]); @@ -283,5 +303,6 @@ int CV_CannyTest::validate_test_results( int test_case_idx ) } TEST(Imgproc_Canny, accuracy) { CV_CannyTest test; test.safe_run(); } +TEST(Imgproc_Canny, accuracy_deriv) { CV_CannyTest test(true); test.safe_run(); } /* End of file. */ diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 2dac2110e9..2e65a365d9 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -349,8 +349,8 @@ IMPLEMENT_PARAM_CLASS(Channels, int) #define OCL_TEST_F(name, ...) typedef name OCL_##name; TEST_F(OCL_##name, __VA_ARGS__) #define OCL_TEST(name, ...) TEST(OCL_##name, __VA_ARGS__) -#define OCL_OFF(fn) cv::ocl::setUseOpenCL(false); fn -#define OCL_ON(fn) cv::ocl::setUseOpenCL(true); fn +#define OCL_OFF(...) cv::ocl::setUseOpenCL(false); __VA_ARGS__ ; +#define OCL_ON(...) cv::ocl::setUseOpenCL(true); __VA_ARGS__ ; #define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F) #define OCL_ALL_CHANNELS Values(1, 2, 3, 4) From 96edb270a6bd856b1361dd5b50e46815386a1c74 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 16 Jul 2016 17:55:54 +0300 Subject: [PATCH 085/153] fixed memory corruption when normal dist. params have less channels than target matrix; test added --- modules/core/src/rand.cpp | 14 +++++++------- modules/core/test/test_rand.cpp | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 9bfc91d931..5d389c56d4 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -624,7 +624,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, int ptype = depth == CV_64F ? CV_64F : CV_32F; int esz = (int)CV_ELEM_SIZE(ptype); - if( _param1.isContinuous() && _param1.type() == ptype ) + if( _param1.isContinuous() && _param1.type() == ptype && n1 >= cn) mean = _param1.ptr(); else { @@ -637,18 +637,18 @@ void RNG::fill( InputOutputArray _mat, int disttype, for( j = n1*esz; j < cn*esz; j++ ) mean[j] = mean[j - n1*esz]; - if( _param2.isContinuous() && _param2.type() == ptype ) + if( _param2.isContinuous() && _param2.type() == ptype && n2 >= cn) stddev = _param2.ptr(); else { - Mat tmp(_param2.size(), ptype, parambuf + cn); + Mat tmp(_param2.size(), ptype, parambuf + MAX(n1, cn)); _param2.convertTo(tmp, ptype); - stddev = (uchar*)(parambuf + cn); + stddev = (uchar*)(parambuf + MAX(n1, cn)); } - if( n1 < cn ) - for( j = n1*esz; j < cn*esz; j++ ) - stddev[j] = stddev[j - n1*esz]; + if( n2 < cn ) + for( j = n2*esz; j < cn*esz; j++ ) + stddev[j] = stddev[j - n2*esz]; stdmtx = _param2.rows == cn && _param2.cols == cn; scaleFunc = randnScaleTab[depth]; diff --git a/modules/core/test/test_rand.cpp b/modules/core/test/test_rand.cpp index fc6c75aac1..63b9094177 100644 --- a/modules/core/test/test_rand.cpp +++ b/modules/core/test/test_rand.cpp @@ -365,3 +365,20 @@ TEST(Core_RNG_MT19937, regression) ASSERT_EQ(expected[i], actual[i]); } } + + +TEST(Core_Rand, Regression_Stack_Corruption) +{ + int bufsz = 128; //enough for 14 doubles + AutoBuffer buffer(bufsz); + size_t offset = 0; + cv::Mat_ x(2, 3, (cv::Point2d*)(buffer+offset)); offset += x.total()*x.elemSize(); + double& param1 = *(double*)(buffer+offset); offset += sizeof(double); + double& param2 = *(double*)(buffer+offset); offset += sizeof(double); + param1 = -9; param2 = 2; + + cv::theRNG().fill(x, cv::RNG::NORMAL, param1, param2); + + ASSERT_EQ(param1, -9); + ASSERT_EQ(param2, 2); +} From 0e9c8e2dd5f20ffbedbe0af1b9aaa6b104f7ffca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Br=C3=83=C2=A1s?= Date: Fri, 15 Jul 2016 19:55:19 -0300 Subject: [PATCH 086/153] 'resolves' 6898 I have seen that you can input a Mat_ on StereoBM, but the value seems the same as CV_16S. I changed it so, only if you input a Mat_ it makes use of a previously truncated 4 bits, giving more resolution to Disparity Matrix. (The algorithm stays the same, it's not more precise). If any other input Mat is given, it changes nothing. --- modules/calib3d/src/stereobm.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 83ed9ae0c5..9df5100807 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -317,7 +317,9 @@ prefilterXSobel( const Mat& src, Mat& dst, int ftzero ) } -static const int DISPARITY_SHIFT = 4; +static int DISPARITY_SHIFT; +static const int DISPARITY_SHIFT_16S = 4; +static const int DISPARITY_SHIFT_32S = 8; #if CV_SSE2 static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right, @@ -568,8 +570,9 @@ static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right, } #endif +template static void -findStereoCorrespondenceBM( const Mat& left, const Mat& right, +findStereoCorrespondenceBM_( const Mat& left, const Mat& right, Mat& disp, Mat& cost, const StereoBMParams& state, uchar* buf, int _dy0, int _dy1 ) { @@ -587,7 +590,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right, int ftzero = state.preFilterCap; int textureThreshold = state.textureThreshold; int uniquenessRatio = state.uniquenessRatio; - short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT); + mType FILTERED = (mType)((mindisp - 1) << DISPARITY_SHIFT); #if CV_NEON CV_Assert (ndisp % 8 == 0); @@ -603,7 +606,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right, const uchar* lptr0 = left.ptr() + lofs; const uchar* rptr0 = right.ptr() + rofs; const uchar *lptr, *lptr_sub, *rptr; - short* dptr = disp.ptr(); + mType* dptr = disp.ptr(); int sstep = (int)left.step; int dstep = (int)(disp.step/sizeof(dptr[0])); int cstep = (height+dy0+dy1)*ndisp; @@ -846,13 +849,30 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right, sad[ndisp] = sad[ndisp-2]; int p = sad[mind+1], n = sad[mind-1]; d = p + n - 2*sad[mind] + std::abs(p - n); - dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*256/d : 0) + 15) >> 4); + dptr[y*dstep] = (mType)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*256/d : 0) + 15) + >> (DISPARITY_SHIFT_32S - DISPARITY_SHIFT)); costptr[y*coststep] = sad[mind]; } } } } +static void +findStereoCorrespondenceBM( const Mat& left, const Mat& right, + Mat& disp, Mat& cost, const StereoBMParams& state, + uchar* buf, int _dy0, int _dy1 ) +{ + if(disp.type() == CV_16S){ + DISPARITY_SHIFT = DISPARITY_SHIFT_16S; + findStereoCorrespondenceBM_(left, right, disp, cost, state, + buf, _dy0, _dy1 ); + } else { + DISPARITY_SHIFT = DISPARITY_SHIFT_32S; + findStereoCorrespondenceBM_(left, right, disp, cost, state, + buf, _dy0, _dy1 ); + } +} + #ifdef HAVE_OPENCL static bool ocl_prefiltering(InputArray left0, InputArray right0, OutputArray left, OutputArray right, StereoBMParams* state) { @@ -1129,7 +1149,7 @@ public: Mat disp = disp0; if( dtype == CV_32F ) { - dispbuf.create(disp0.size(), CV_16S); + dispbuf.create(disp0.size(), CV_32S); disp = dispbuf; } From b436f4b995bd3d0f7d5bb21389982149e09da113 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Wed, 20 Jul 2016 08:28:49 +0900 Subject: [PATCH 087/153] accelerate bilateralFilter using NEON * clean up some lines --- modules/imgproc/src/smooth.cpp | 135 ++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 12 deletions(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 952d4e3fd2..b5a037ec2d 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -3017,16 +3017,16 @@ public: _g = _mm_mul_ps(_g, _w); _r = _mm_mul_ps(_r, _w); - _w = _mm_hadd_ps(_w, _b); - _g = _mm_hadd_ps(_g, _r); + _w = _mm_hadd_ps(_w, _b); + _g = _mm_hadd_ps(_g, _r); - _w = _mm_hadd_ps(_w, _g); - _mm_store_ps(bufSum, _w); + _w = _mm_hadd_ps(_w, _g); + _mm_store_ps(bufSum, _w); - wsum += bufSum[0]; - sum_b += bufSum[1]; - sum_g += bufSum[2]; - sum_r += bufSum[3]; + wsum += bufSum[0]; + sum_b += bufSum[1]; + sum_g += bufSum[2]; + sum_r += bufSum[3]; } } #endif @@ -3293,11 +3293,15 @@ public: { int i, j, k; Size size = dest->size(); - #if CV_SSE3 + #if CV_SSE3 || CV_NEON int CV_DECL_ALIGNED(16) idxBuf[4]; float CV_DECL_ALIGNED(16) bufSum32[4]; static const unsigned int CV_DECL_ALIGNED(16) bufSignMask[] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + #endif + #if CV_SSE3 bool haveSSE3 = checkHardwareSupport(CV_CPU_SSE3); + #elif CV_NEON + bool haveNEON = checkHardwareSupport(CV_CPU_NEON); #endif for( i = range.start; i < range.end; i++ ) @@ -3339,15 +3343,56 @@ public: __m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut)))); _val = _mm_mul_ps(_w, _val); - _sw = _mm_hadd_ps(_w, _val); - _sw = _mm_hadd_ps(_sw, _sw); - psum = _mm_add_ps(_sw, psum); + _sw = _mm_hadd_ps(_w, _val); + _sw = _mm_hadd_ps(_sw, _sw); + psum = _mm_add_ps(_sw, psum); } _mm_storel_pi((__m64*)bufSum32, psum); sum = bufSum32[1]; wsum = bufSum32[0]; } + #elif CV_NEON + if( haveNEON ) + { + float32x2_t psum = vdup_n_f32(0.0f); + const volatile float32x4_t _val0 = vdupq_n_f32(sptr[j]); + const float32x4_t _scale_index = vdupq_n_f32(scale_index); + const uint32x4_t _signMask = vld1q_u32(bufSignMask); + + for( ; k <= maxk - 4 ; k += 4 ) + { + float32x4_t _sw = vld1q_f32(space_weight + k); + float CV_DECL_ALIGNED(16) _data[] = {sptr[j + space_ofs[k]], sptr[j + space_ofs[k+1]], + sptr[j + space_ofs[k+2]], sptr[j + space_ofs[k+3]],}; + float32x4_t _val = vld1q_f32(_data); + float32x4_t _alpha = vsubq_f32(_val, _val0); + _alpha = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(_alpha), _signMask)); + _alpha = vmulq_f32(_alpha, _scale_index); + int32x4_t _idx = vcvtq_s32_f32(_alpha); + vst1q_s32(idxBuf, _idx); + _alpha = vsubq_f32(_alpha, vcvtq_f32_s32(_idx)); + + bufSum32[0] = expLUT[idxBuf[0]]; + bufSum32[1] = expLUT[idxBuf[1]]; + bufSum32[2] = expLUT[idxBuf[2]]; + bufSum32[3] = expLUT[idxBuf[3]]; + float32x4_t _explut = vld1q_f32(bufSum32); + bufSum32[0] = expLUT[idxBuf[0]+1]; + bufSum32[1] = expLUT[idxBuf[1]+1]; + bufSum32[2] = expLUT[idxBuf[2]+1]; + bufSum32[3] = expLUT[idxBuf[3]+1]; + float32x4_t _explut1 = vld1q_f32(bufSum32); + + float32x4_t _w = vmulq_f32(_sw, vaddq_f32(_explut, vmulq_f32(_alpha, vsubq_f32(_explut1, _explut)))); + _val = vmulq_f32(_w, _val); + + float32x2_t _wval = vpadd_f32(vpadd_f32(vget_low_f32(_w),vget_high_f32(_w)), vpadd_f32(vget_low_f32(_val), vget_high_f32(_val))); + psum = vadd_f32(_wval, psum); + } + sum = vget_lane_f32(psum, 1); + wsum = vget_lane_f32(psum, 0); + } #endif for( ; k < maxk; k++ ) @@ -3427,6 +3472,72 @@ public: sum_g = bufSum32[2]; sum_r = bufSum32[3]; } + #elif CV_NEON + if( haveNEON ) + { + float32x4_t sum = vdupq_n_f32(0.0f); + const float32x4_t _b0 = vdupq_n_f32(b0); + const float32x4_t _g0 = vdupq_n_f32(g0); + const float32x4_t _r0 = vdupq_n_f32(r0); + const float32x4_t _scale_index = vdupq_n_f32(scale_index); + const uint32x4_t _signMask = vld1q_u32(bufSignMask); + + for( ; k <= maxk-4; k += 4 ) + { + float32x4_t _sw = vld1q_f32(space_weight + k); + + const float* const sptr_k0 = sptr + j + space_ofs[k]; + const float* const sptr_k1 = sptr + j + space_ofs[k+1]; + const float* const sptr_k2 = sptr + j + space_ofs[k+2]; + const float* const sptr_k3 = sptr + j + space_ofs[k+3]; + + float32x4_t _v0 = vld1q_f32(sptr_k0); + float32x4_t _v1 = vld1q_f32(sptr_k1); + float32x4_t _v2 = vld1q_f32(sptr_k2); + float32x4_t _v3 = vld1q_f32(sptr_k3); + + float32x4x2_t v01 = vtrnq_f32(_v0, _v1); + float32x4x2_t v23 = vtrnq_f32(_v2, _v3); + float32x4_t _b = vcombine_f32(vget_low_f32(v01.val[0]), vget_low_f32(v23.val[0])); + float32x4_t _g = vcombine_f32(vget_low_f32(v01.val[1]), vget_low_f32(v23.val[1])); + float32x4_t _r = vcombine_f32(vget_high_f32(v01.val[0]), vget_high_f32(v23.val[0])); + + float32x4_t _bt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_b, _b0)), _signMask)); + float32x4_t _gt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_g, _g0)), _signMask)); + float32x4_t _rt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_r, _r0)), _signMask)); + float32x4_t _alpha = vmulq_f32(_scale_index, vaddq_f32(_bt, vaddq_f32(_gt, _rt))); + + int32x4_t _idx = vcvtq_s32_f32(_alpha); + vst1q_s32((int*)idxBuf, _idx); + bufSum32[0] = expLUT[idxBuf[0]]; + bufSum32[1] = expLUT[idxBuf[1]]; + bufSum32[2] = expLUT[idxBuf[2]]; + bufSum32[3] = expLUT[idxBuf[3]]; + float32x4_t _explut = vld1q_f32(bufSum32); + bufSum32[0] = expLUT[idxBuf[0]+1]; + bufSum32[1] = expLUT[idxBuf[1]+1]; + bufSum32[2] = expLUT[idxBuf[2]+1]; + bufSum32[3] = expLUT[idxBuf[3]+1]; + float32x4_t _explut1 = vld1q_f32(bufSum32); + + float32x4_t _w = vmulq_f32(_sw, vaddq_f32(_explut, vmulq_f32(_alpha, vsubq_f32(_explut1, _explut)))); + + _b = vmulq_f32(_b, _w); + _g = vmulq_f32(_g, _w); + _r = vmulq_f32(_r, _w); + + float32x2_t _wb = vpadd_f32(vpadd_f32(vget_low_f32(_w),vget_high_f32(_w)), vpadd_f32(vget_low_f32(_b), vget_high_f32(_b))); + float32x2_t _gr = vpadd_f32(vpadd_f32(vget_low_f32(_g),vget_high_f32(_g)), vpadd_f32(vget_low_f32(_r), vget_high_f32(_r))); + + _w = vcombine_f32(_wb, _gr); + sum = vaddq_f32(sum, _w); + } + vst1q_f32(bufSum32, sum); + wsum = bufSum32[0]; + sum_b = bufSum32[1]; + sum_g = bufSum32[2]; + sum_r = bufSum32[3]; + } #endif for(; k < maxk; k++ ) From 71cbd6f02eb4480970d38ed08132e8b9e5503b05 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 19 Jul 2016 15:53:52 +0300 Subject: [PATCH 088/153] fixed bug #5775 --- modules/core/src/arithm.cpp | 2 +- modules/core/test/test_arithm.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 8ef3370bde..fc20a18311 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -643,7 +643,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, if (!muldiv) { Mat sc = psrc2->getMat(); - depth2 = actualScalarDepth(sc.ptr(), cn); + depth2 = actualScalarDepth(sc.ptr(), sz2 == Size(1, 1) ? cn2 : cn); if( depth2 == CV_64F && (depth1 < CV_32S || depth1 == CV_32F) ) depth2 = CV_32F; } diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 21c16b9c47..1289b73e39 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1910,3 +1910,21 @@ TEST(MinMaxLoc, regression_4955_nans) cv::Mat nan_mat(2, 2, CV_32F, cv::Scalar(NAN)); cv::minMaxLoc(nan_mat, NULL, NULL, NULL, NULL); } + +TEST(Subtract, scalarc1_matc3) +{ + int scalar = 255; + cv::Mat srcImage(5, 5, CV_8UC3, cv::Scalar::all(5)), destImage; + cv::subtract(scalar, srcImage, destImage); + + ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC3, cv::Scalar::all(250)), destImage, cv::NORM_INF)); +} + +TEST(Subtract, scalarc4_matc4) +{ + cv::Scalar sc(255, 255, 255, 255); + cv::Mat srcImage(5, 5, CV_8UC4, cv::Scalar::all(5)), destImage; + cv::subtract(sc, srcImage, destImage); + + ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC4, cv::Scalar::all(250)), destImage, cv::NORM_INF)); +} From 8a65e73bfdad4aeb9ee8bbb9ca345356aa5de53c Mon Sep 17 00:00:00 2001 From: MYLS Date: Wed, 20 Jul 2016 20:18:16 +0800 Subject: [PATCH 089/153] add SANITY_CHECK_NOTHING() to perf_test --- modules/core/perf/perf_io_base64.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/core/perf/perf_io_base64.cpp b/modules/core/perf/perf_io_base64.cpp index f2982b2cb0..04a4a040a5 100644 --- a/modules/core/perf/perf_io_base64.cpp +++ b/modules/core/perf/perf_io_base64.cpp @@ -47,6 +47,7 @@ PERF_TEST_P(Size_Mat_StrType, fs_text, } remove(file_name.c_str()); + SANITY_CHECK_NOTHING(); } PERF_TEST_P(Size_Mat_StrType, fs_base64, @@ -81,4 +82,5 @@ PERF_TEST_P(Size_Mat_StrType, fs_base64, } remove(file_name.c_str()); + SANITY_CHECK_NOTHING(); } From 2ec63e4dd1bd97298efebb9ab9312caff5e06c22 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 18 Jul 2016 17:45:16 +0300 Subject: [PATCH 090/153] fix android pack build --- cmake/OpenCVCompilerOptions.cmake | 15 +++++++++++ cmake/checks/fp16.cpp | 33 +++++++++++++++++++++++ cmake/templates/cvconfig.h.in | 3 +++ modules/core/include/opencv2/core/cvdef.h | 12 ++++++--- modules/core/src/convert.cpp | 4 +++ modules/imgproc/src/thresh.cpp | 17 ++++++++++++ 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 cmake/checks/fp16.cpp diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index d0c28ab0fb..a2c118db43 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -369,3 +369,18 @@ if(MSVC) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4589) # Constructor of abstract class 'cv::ORB' ignores initializer for virtual base class 'cv::Algorithm' endif() endif() + +if(NOT OPENCV_FP16_DISABLE) + try_compile(__VALID_FP16 + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/fp16.cpp" + COMPILE_DEFINITIONS "-DCHECK_FP16" + OUTPUT_VARIABLE TRY_OUT + ) + if(NOT __VALID_FP16) + message(STATUS "FP16: Compiler support is not available") + else() + message(STATUS "FP16: Compiler support is available") + set(HAVE_FP16 1) + endif() +endif() diff --git a/cmake/checks/fp16.cpp b/cmake/checks/fp16.cpp new file mode 100644 index 0000000000..c77c844834 --- /dev/null +++ b/cmake/checks/fp16.cpp @@ -0,0 +1,33 @@ +#include + +#if defined __F16C__ || (defined _MSC_VER && _MSC_VER >= 1700) +#include +int test() +{ + const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + short dst[8]; + __m128 v_src = _mm_load_ps(src); + __m128i v_dst = _mm_cvtps_ph(v_src, 0); + _mm_storel_epi64((__m128i*)dst, v_dst); + return (int)dst[0]; +} +#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) +#include "arm_neon.h" +int test() +{ + const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + short dst[8]; + float32x4_t v_src = *(float32x4_t*)src; + float16x4_t v_dst = vcvt_f16_f32(v_src); + *(float16x4_t*)dst = v_dst; + return (int)dst[0]; +} +#else +#error "FP16 is not supported" +#endif + +int main() +{ + printf("%d\n", test()); + return 0; +} diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 2312742130..8dac1ed618 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -203,3 +203,6 @@ /* Lapack */ #cmakedefine HAVE_LAPACK + +/* FP16 */ +#cmakedefine HAVE_FP16 diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 42e93118b7..5ff8ec4213 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -193,7 +193,7 @@ enum CpuFeatures { # endif # define CV_POPCNT 1 # endif -# if defined __F16C__ || (defined _MSC_VER && _MSC_VER >= 1700) +# if defined HAVE_FP16 && (defined __F16C__ || (defined _MSC_VER && _MSC_VER >= 1700)) # include # define CV_FP16 1 # endif @@ -219,7 +219,7 @@ enum CpuFeatures { #if (defined WIN32 || defined _WIN32) && defined(_M_ARM) # include -# include "arm_neon.h" +# include # define CV_NEON 1 # define CPU_HAS_NEON_FEATURE (true) #elif defined(__ARM_NEON__) || (defined (__ARM_NEON) && defined(__aarch64__)) @@ -227,8 +227,12 @@ enum CpuFeatures { # define CV_NEON 1 #endif -#if defined __GNUC__ && ((defined (__arm__) && (__ARM_FP & 0x2)) || defined(__aarch64__)) -# define CV_FP16 1 +#if defined(__ARM_NEON__) || defined(__aarch64__) +# include +#endif + +#if defined HAVE_FP16 && defined __GNUC__ +# define CV_FP16 1 #endif #if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__ || defined __ARM_NEON__) && !defined __SOFTFP__ diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index e5c5e43690..dff0f9bc64 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -4591,6 +4591,8 @@ cvtScaleHalf_( const float* src, size_t sstep, short* dst, size_t float16x4_t v_dst = vcvt_f16_f32(v_src); *(float16x4_t*)(dst + x) = v_dst; +#else +#error "Configuration error" #endif } #endif @@ -4643,6 +4645,8 @@ cvtScaleHalf_( const short* src, size_t sstep, float* dst, size_t float32x4_t v_dst = vcvt_f32_f16(v_src); *(float32x4_t*)(dst + x) = v_dst; +#else +#error "Configuration error" #endif } #endif diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index a63c59ef34..e133de3f29 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -43,6 +43,23 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#if CV_NEON && defined(__aarch64__) +#include +namespace cv { +// Workaround with missing definitions of vreinterpretq_u64_f64/vreinterpretq_f64_u64 +template static inline +uint64x2_t vreinterpretq_u64_f64(T a) +{ + return (uint64x2_t) a; +} +template static inline +float64x2_t vreinterpretq_f64_u64(T a) +{ + return (float64x2_t) a; +} +} // namespace cv +#endif + namespace cv { From 60676dbbe8149dc98824c8e565074d9f4e81f61a Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 20 Jul 2016 16:17:57 +0300 Subject: [PATCH 091/153] fix build: move LOG macro from stitching public headers --- .../include/opencv2/stitching/detail/util.hpp | 50 ---------------- modules/stitching/src/precomp.hpp | 2 + modules/stitching/src/util_log.hpp | 58 +++++++++++++++++++ samples/cpp/stitching_detailed.cpp | 5 +- 4 files changed, 64 insertions(+), 51 deletions(-) create mode 100644 modules/stitching/src/util_log.hpp diff --git a/modules/stitching/include/opencv2/stitching/detail/util.hpp b/modules/stitching/include/opencv2/stitching/detail/util.hpp index 3845ba59ea..e746f5e8bf 100644 --- a/modules/stitching/include/opencv2/stitching/detail/util.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/util.hpp @@ -46,56 +46,6 @@ #include #include "opencv2/core.hpp" -#ifndef ENABLE_LOG -#define ENABLE_LOG 0 -#endif - -// TODO remove LOG macros, add logging class -#if ENABLE_LOG -#ifdef ANDROID - #include - #include - #include - #define LOG_STITCHING_MSG(msg) \ - do { \ - Stringstream _os; \ - _os << msg; \ - __android_log_print(ANDROID_LOG_DEBUG, "STITCHING", "%s", _os.str().c_str()); \ - } while(0); -#else - #include - #define LOG_STITCHING_MSG(msg) for(;;) { std::cout << msg; std::cout.flush(); break; } -#endif -#else - #define LOG_STITCHING_MSG(msg) -#endif - -#define LOG_(_level, _msg) \ - for(;;) \ - { \ - using namespace std; \ - if ((_level) >= ::cv::detail::stitchingLogLevel()) \ - { \ - LOG_STITCHING_MSG(_msg); \ - } \ - break; \ - } - - -#define LOG(msg) LOG_(1, msg) -#define LOG_CHAT(msg) LOG_(0, msg) - -#define LOGLN(msg) LOG(msg << std::endl) -#define LOGLN_CHAT(msg) LOG_CHAT(msg << std::endl) - -//#if DEBUG_LOG_CHAT -// #define LOG_CHAT(msg) LOG(msg) -// #define LOGLN_CHAT(msg) LOGLN(msg) -//#else -// #define LOG_CHAT(msg) do{}while(0) -// #define LOGLN_CHAT(msg) do{}while(0) -//#endif - namespace cv { namespace detail { diff --git a/modules/stitching/src/precomp.hpp b/modules/stitching/src/precomp.hpp index 70636b6848..eff78cf585 100644 --- a/modules/stitching/src/precomp.hpp +++ b/modules/stitching/src/precomp.hpp @@ -99,4 +99,6 @@ # include "opencv2/stitching/stitching_tegra.hpp" #endif +#include "util_log.hpp" + #endif diff --git a/modules/stitching/src/util_log.hpp b/modules/stitching/src/util_log.hpp new file mode 100644 index 0000000000..da454777cb --- /dev/null +++ b/modules/stitching/src/util_log.hpp @@ -0,0 +1,58 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef __OPENCV_STITCHING_UTIL_LOG_HPP__ +#define __OPENCV_STITCHING_UTIL_LOG_HPP__ + +#ifndef ENABLE_LOG +#define ENABLE_LOG 0 +#endif + +// TODO remove LOG macros, add logging class +#if ENABLE_LOG +#ifdef ANDROID + #include + #include + #include + #define LOG_STITCHING_MSG(msg) \ + do { \ + Stringstream _os; \ + _os << msg; \ + __android_log_print(ANDROID_LOG_DEBUG, "STITCHING", "%s", _os.str().c_str()); \ + } while(0); +#else + #include + #define LOG_STITCHING_MSG(msg) for(;;) { std::cout << msg; std::cout.flush(); break; } +#endif +#else + #define LOG_STITCHING_MSG(msg) +#endif + +#define LOG_(_level, _msg) \ + for(;;) \ + { \ + using namespace std; \ + if ((_level) >= ::cv::detail::stitchingLogLevel()) \ + { \ + LOG_STITCHING_MSG(_msg); \ + } \ + break; \ + } + + +#define LOG(msg) LOG_(1, msg) +#define LOG_CHAT(msg) LOG_(0, msg) + +#define LOGLN(msg) LOG(msg << std::endl) +#define LOGLN_CHAT(msg) LOG_CHAT(msg << std::endl) + +//#if DEBUG_LOG_CHAT +// #define LOG_CHAT(msg) LOG(msg) +// #define LOGLN_CHAT(msg) LOGLN(msg) +//#else +// #define LOG_CHAT(msg) do{}while(0) +// #define LOGLN_CHAT(msg) do{}while(0) +//#endif + +#endif // __OPENCV_STITCHING_UTIL_LOG_HPP__ diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index 8fc489e870..f333bc6e36 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -56,10 +56,13 @@ #include "opencv2/stitching/detail/matchers.hpp" #include "opencv2/stitching/detail/motion_estimators.hpp" #include "opencv2/stitching/detail/seam_finders.hpp" -#include "opencv2/stitching/detail/util.hpp" #include "opencv2/stitching/detail/warpers.hpp" #include "opencv2/stitching/warpers.hpp" +#define ENABLE_LOG 1 +#define LOG(msg) std::cout << msg +#define LOGLN(msg) std::cout << msg << std::endl + using namespace std; using namespace cv; using namespace cv::detail; From daf1879a2e5ea9a21c2e1c5209bc5c6526aa112e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 15 Jul 2016 17:00:02 +0300 Subject: [PATCH 092/153] test: ffmpeg: change resolution for H264 test --- modules/videoio/test/test_ffmpeg.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/videoio/test/test_ffmpeg.cpp b/modules/videoio/test/test_ffmpeg.cpp index 423817715a..fce8cf467c 100644 --- a/modules/videoio/test/test_ffmpeg.cpp +++ b/modules/videoio/test/test_ffmpeg.cpp @@ -118,6 +118,9 @@ public: frame_s = Size(352, 288); else if( tag == VideoWriter::fourcc('H', '2', '6', '3') ) frame_s = Size(704, 576); + else if( tag == VideoWriter::fourcc('H', '2', '6', '4') ) + // OpenH264 1.5.0 has resolution limitations, so lets use DCI 4K resolution + frame_s = Size(4096, 2160); /*else if( tag == CV_FOURCC('M', 'J', 'P', 'G') || tag == CV_FOURCC('j', 'p', 'e', 'g') ) frame_s = Size(1920, 1080);*/ From 57d1591957e9be6ae16e6c11a239a5c59a7f2660 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Thu, 21 Jul 2016 06:42:11 +0900 Subject: [PATCH 093/153] imgproc: fix typo * indent line --- modules/imgproc/src/imgwarp.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 54054883df..ff96c2fe1e 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -4617,14 +4617,14 @@ static bool ocl_linearPolar(InputArray _src, OutputArray _dst, size_t w = dsize.width; size_t h = dsize.height; String buildOptions; - unsigned mem_szie = 32; + unsigned mem_size = 32; if (flags & CV_WARP_INVERSE_MAP) { buildOptions = "-D InverseMap"; } else { - buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_szie); + buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_size); } String retval; ocl::Program p(ocl::imgproc::linearPolar_oclsrc, buildOptions, retval); @@ -4662,7 +4662,7 @@ static bool ocl_linearPolar(InputArray _src, OutputArray _dst, } size_t globalThreads[2] = { (size_t)dsize.width , (size_t)dsize.height }; - size_t localThreads[2] = { mem_szie , mem_szie }; + size_t localThreads[2] = { mem_size , mem_size }; k.run(2, globalThreads, localThreads, false); remap(src, _dst, mapx, mapy, flags & cv::INTER_MAX, (flags & CV_WARP_FILL_OUTLIERS) ? cv::BORDER_CONSTANT : cv::BORDER_TRANSPARENT); return true; @@ -4686,14 +4686,14 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst, size_t w = dsize.width; size_t h = dsize.height; String buildOptions; - unsigned mem_szie = 32; + unsigned mem_size = 32; if (flags & CV_WARP_INVERSE_MAP) { buildOptions = "-D InverseMap"; } else { - buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_szie); + buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_size); } String retval; ocl::Program p(ocl::imgproc::logPolar_oclsrc, buildOptions, retval); @@ -4731,9 +4731,9 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst, k.args(ocl_mapx, ocl_mapy, ascale, (float)M, center.x, center.y, ANGLE_BORDER, (unsigned)dsize.width, (unsigned)dsize.height); -} + } size_t globalThreads[2] = { (size_t)dsize.width , (size_t)dsize.height }; - size_t localThreads[2] = { mem_szie , mem_szie }; + size_t localThreads[2] = { mem_size , mem_size }; k.run(2, globalThreads, localThreads, false); remap(src, _dst, mapx, mapy, flags & cv::INTER_MAX, (flags & CV_WARP_FILL_OUTLIERS) ? cv::BORDER_CONSTANT : cv::BORDER_TRANSPARENT); return true; From 440ba2e4a7c9b1d0773abf3f955c6ecd9f84fe7a Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 20 Jul 2016 22:57:55 -0300 Subject: [PATCH 094/153] Passing Disparity Shift as a parameter. --- modules/calib3d/src/stereobm.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 9df5100807..98a4d69393 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -317,7 +317,6 @@ prefilterXSobel( const Mat& src, Mat& dst, int ftzero ) } -static int DISPARITY_SHIFT; static const int DISPARITY_SHIFT_16S = 4; static const int DISPARITY_SHIFT_32S = 8; @@ -574,7 +573,7 @@ template static void findStereoCorrespondenceBM_( const Mat& left, const Mat& right, Mat& disp, Mat& cost, const StereoBMParams& state, - uchar* buf, int _dy0, int _dy1 ) + uchar* buf, int _dy0, int _dy1, const int disp_shift ) { const int ALIGN = 16; @@ -590,7 +589,7 @@ findStereoCorrespondenceBM_( const Mat& left, const Mat& right, int ftzero = state.preFilterCap; int textureThreshold = state.textureThreshold; int uniquenessRatio = state.uniquenessRatio; - mType FILTERED = (mType)((mindisp - 1) << DISPARITY_SHIFT); + mType FILTERED = (mType)((mindisp - 1) << disp_shift); #if CV_NEON CV_Assert (ndisp % 8 == 0); @@ -850,7 +849,7 @@ findStereoCorrespondenceBM_( const Mat& left, const Mat& right, int p = sad[mind+1], n = sad[mind-1]; d = p + n - 2*sad[mind] + std::abs(p - n); dptr[y*dstep] = (mType)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*256/d : 0) + 15) - >> (DISPARITY_SHIFT_32S - DISPARITY_SHIFT)); + >> (DISPARITY_SHIFT_32S - disp_shift)); costptr[y*coststep] = sad[mind]; } } @@ -862,15 +861,12 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right, Mat& disp, Mat& cost, const StereoBMParams& state, uchar* buf, int _dy0, int _dy1 ) { - if(disp.type() == CV_16S){ - DISPARITY_SHIFT = DISPARITY_SHIFT_16S; + if(disp.type() == CV_16S) findStereoCorrespondenceBM_(left, right, disp, cost, state, - buf, _dy0, _dy1 ); - } else { - DISPARITY_SHIFT = DISPARITY_SHIFT_32S; + buf, _dy0, _dy1, DISPARITY_SHIFT_16S ); + else findStereoCorrespondenceBM_(left, right, disp, cost, state, - buf, _dy0, _dy1 ); - } + buf, _dy0, _dy1, DISPARITY_SHIFT_32S ); } #ifdef HAVE_OPENCL From b3d55489d3f1bd2eab0c1e3ad56d8f17d4f447e9 Mon Sep 17 00:00:00 2001 From: Sergei Nosov Date: Thu, 21 Jul 2016 10:57:58 +0300 Subject: [PATCH 095/153] fix compiler warning --- modules/calib3d/test/test_cameracalibration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 357208dd6c..523594224d 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1440,7 +1440,7 @@ void CV_StereoCalibrationCornerTest::run(int) // result as calibrating the downscaled images int cnz = countNonZero((cv::Mat(src_result - rsz_result) != 0)( cv::Rect(src_result.cols / 3, src_result.rows / 3, - src_result.cols / 3.1, src_result.rows / 3.1))); + (int)(src_result.cols / 3.1), int(src_result.rows / 3.1)))); if (cnz) { ts->printf( cvtest::TS::LOG, "The camera matrix is wrong for downscaled image\n"); From 313f54bc397bf789dcc829ff1f68e3d6c9ed98c1 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 20 Jul 2016 12:25:30 +0300 Subject: [PATCH 096/153] read/write vec2i from/to filestorage --- modules/core/test/test_io.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index f2c53dc964..568b3d26a2 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -740,3 +740,28 @@ TEST(Core_InputOutput, filestorage_xml_base64) { CV_Base64IOTest test("base64_test_tmp_file.xml"); test.safe_run(); } + +TEST(Core_InputOutput, filestorage_yml_vec2i) +{ + const std::string file_name = "vec2i.yml"; + cv::Vec2i vec(2, 1), ovec; + + /* write */ + { + cv::FileStorage fs(file_name, cv::FileStorage::WRITE); + fs << "prms0" << "{" << "vec0" << vec << "}"; + fs.release(); + } + + /* read */ + { + cv::FileStorage fs(file_name, cv::FileStorage::READ); + fs["prms0"]["vec0"] >> ovec; + fs.release(); + } + + EXPECT_EQ(vec(0), ovec(0)); + EXPECT_EQ(vec(1), ovec(1)); + + remove(file_name.c_str()); +} From 82e4e1816f5417637b26496009fb239302bee325 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Thu, 21 Jul 2016 17:51:19 +0300 Subject: [PATCH 097/153] highgui: removed excessed variable orient in window_gtk --- modules/highgui/src/window_gtk.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 475f85f9f6..c769879bdd 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1970,9 +1970,9 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da #if defined(GTK_VERSION3_4) // NOTE: in current implementation doesn't possible to put into callback function delta_x and delta_y separetely double delta = (event->scroll.delta_x + event->scroll.delta_y); - int orient = (event->scroll.delta_y!=0) ? CV_EVENT_MOUSEHWHEEL : CV_EVENT_MOUSEWHEEL; + cv_event = (event->scroll.delta_y!=0) ? CV_EVENT_MOUSEHWHEEL : CV_EVENT_MOUSEWHEEL; #else - int orient = CV_EVENT_MOUSEWHEEL; + cv_event = CV_EVENT_MOUSEWHEEL; #endif //GTK_VERSION3_4 state = event->scroll.state; @@ -1982,15 +1982,14 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da case GDK_SCROLL_SMOOTH: flags |= (((int)delta << 16)); break; #endif //GTK_VERSION3_4 - case GDK_SCROLL_LEFT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_LEFT: cv_event = CV_EVENT_MOUSEHWHEEL; case GDK_SCROLL_UP: flags |= ((-(int)1 << 16)); break; - case GDK_SCROLL_RIGHT: orient = CV_EVENT_MOUSEHWHEEL; + case GDK_SCROLL_RIGHT: cv_event = CV_EVENT_MOUSEHWHEEL; case GDK_SCROLL_DOWN: flags |= (((int)1 << 16)); break; default: ; }; - cv_event = orient; } if( cv_event >= 0 ) From 13aef2c0cff94d241569844e02c3dbb3ac301330 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Thu, 21 Jul 2016 18:13:42 +0300 Subject: [PATCH 098/153] highgui: window_QT mouse wheel support --- modules/highgui/src/window_QT.cpp | 120 +++++++++++++++++------------- modules/highgui/src/window_QT.h | 6 +- 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 70f3586210..619729c99e 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -2630,17 +2630,17 @@ void DefaultViewPort::resizeEvent(QResizeEvent* evnt) void DefaultViewPort::wheelEvent(QWheelEvent* evnt) { int delta = evnt->delta(); - int cv_event = -1; - int flags = ((delta & 0xffff)<<16) | ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + int flags = (delta & 0xffff)<<16; QPoint pt = evnt->pos(); - icvmouseHandler(evnt, mouse_wheel, cv_event, flags); - icvmouseProcessing(QPoingF(pt), cv_event, flags); + icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags); + icvmouseProcessing(QPointF(pt), cv_event, flags); scaleView(delta / 240.0, pt); viewport()->update(); - QWidget::mouseWheel(evnt); + QWidget::wheelEvent(evnt); } @@ -2857,7 +2857,9 @@ void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event catego Qt::KeyboardModifiers modifiers = evnt->modifiers(); Qt::MouseButtons buttons = evnt->buttons(); - flags = 0; + // This line gives excess flags flushing, with it you cannot predefine flags value. + // icvmouseHandler called with flags == 0 where it really need. + //flags = 0; if(modifiers & Qt::ShiftModifier) flags |= CV_EVENT_FLAG_SHIFTKEY; if(modifiers & Qt::ControlModifier) @@ -2872,23 +2874,24 @@ void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event catego if(buttons & Qt::MidButton) flags |= CV_EVENT_FLAG_MBUTTON; - cv_event = CV_EVENT_MOUSEMOVE; - switch(evnt->button()) - { - case Qt::LeftButton: - cv_event = tableMouseButtons[category][0]; - flags |= CV_EVENT_FLAG_LBUTTON; - break; - case Qt::RightButton: - cv_event = tableMouseButtons[category][1]; - flags |= CV_EVENT_FLAG_RBUTTON; - break; - case Qt::MidButton: - cv_event = tableMouseButtons[category][2]; - flags |= CV_EVENT_FLAG_MBUTTON; - break; - default:; - } + if (cv_event == -1) + switch(evnt->button()) + { + case Qt::LeftButton: + cv_event = tableMouseButtons[category][0]; + flags |= CV_EVENT_FLAG_LBUTTON; + break; + case Qt::RightButton: + cv_event = tableMouseButtons[category][1]; + flags |= CV_EVENT_FLAG_RBUTTON; + break; + case Qt::MidButton: + cv_event = tableMouseButtons[category][2]; + flags |= CV_EVENT_FLAG_MBUTTON; + break; + default: + cv_event = CV_EVENT_MOUSEMOVE; + } } @@ -3191,6 +3194,22 @@ void OpenGlViewPort::paintGL() glDrawCallback(glDrawData); } +void OpenGlViewPort::wheelEvent(QWheelEvent* evnt) +{ + int delta = evnt->delta(); + int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + int flags = (delta & 0xffff)<<16; + QPoint pt = evnt->pos(); + + icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags); + icvmouseProcessing(QPointF(pt), cv_event, flags); + + scaleView(delta / 240.0, pt); + viewport()->update(); + + QWidget::wheelEvent(evnt); +} + void OpenGlViewPort::mousePressEvent(QMouseEvent* evnt) { int cv_event = -1, flags = 0; @@ -3244,42 +3263,41 @@ void OpenGlViewPort::icvmouseHandler(QMouseEvent* evnt, type_mouse_event categor Qt::KeyboardModifiers modifiers = evnt->modifiers(); Qt::MouseButtons buttons = evnt->buttons(); - flags = 0; - if (modifiers & Qt::ShiftModifier) + // This line gives excess flags flushing, with it you cannot predefine flags value. + // icvmouseHandler called with flags == 0 where it really need. + //flags = 0; + if(modifiers & Qt::ShiftModifier) flags |= CV_EVENT_FLAG_SHIFTKEY; - if (modifiers & Qt::ControlModifier) + if(modifiers & Qt::ControlModifier) flags |= CV_EVENT_FLAG_CTRLKEY; - if (modifiers & Qt::AltModifier) + if(modifiers & Qt::AltModifier) flags |= CV_EVENT_FLAG_ALTKEY; - if (buttons & Qt::LeftButton) + if(buttons & Qt::LeftButton) flags |= CV_EVENT_FLAG_LBUTTON; - if (buttons & Qt::RightButton) + if(buttons & Qt::RightButton) flags |= CV_EVENT_FLAG_RBUTTON; - if (buttons & Qt::MidButton) + if(buttons & Qt::MidButton) flags |= CV_EVENT_FLAG_MBUTTON; - cv_event = CV_EVENT_MOUSEMOVE; - switch (evnt->button()) - { - case Qt::LeftButton: - cv_event = tableMouseButtons[category][0]; - flags |= CV_EVENT_FLAG_LBUTTON; - break; - - case Qt::RightButton: - cv_event = tableMouseButtons[category][1]; - flags |= CV_EVENT_FLAG_RBUTTON; - break; - - case Qt::MidButton: - cv_event = tableMouseButtons[category][2]; - flags |= CV_EVENT_FLAG_MBUTTON; - break; - - default: - ; - } + if (cv_event == -1) + switch(evnt->button()) + { + case Qt::LeftButton: + cv_event = tableMouseButtons[category][0]; + flags |= CV_EVENT_FLAG_LBUTTON; + break; + case Qt::RightButton: + cv_event = tableMouseButtons[category][1]; + flags |= CV_EVENT_FLAG_RBUTTON; + break; + case Qt::MidButton: + cv_event = tableMouseButtons[category][2]; + flags |= CV_EVENT_FLAG_MBUTTON; + break; + default: + cv_event = CV_EVENT_MOUSEMOVE; + } } diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index c0769dcc94..16cc9e3853 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -366,12 +366,13 @@ private slots: }; -enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3 }; +enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3, mouse_wheel = 4 }; static const int tableMouseButtons[][3]={ {CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP}, //mouse_up {CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN}, //mouse_down {CV_EVENT_LBUTTONDBLCLK, CV_EVENT_RBUTTONDBLCLK, CV_EVENT_MBUTTONDBLCLK}, //mouse_dbclick - {CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE} //mouse_move + {CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE}, //mouse_move + {0, 0, 0} //mouse_wheel, to prevent exceptions in code }; @@ -436,6 +437,7 @@ protected: void resizeGL(int w, int h); void paintGL(); + void wheelEvent(QWheelEvent* event); void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); From 531b8e23208b740e707712c85905e2e7eb4dc4fd Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Fri, 22 Jul 2016 07:04:37 +0900 Subject: [PATCH 099/153] add note of minimum requirement of CUDA --- doc/tutorials/introduction/linux_install/linux_install.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/tutorials/introduction/linux_install/linux_install.markdown b/doc/tutorials/introduction/linux_install/linux_install.markdown index 387902dfec..e442e70cec 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.markdown +++ b/doc/tutorials/introduction/linux_install/linux_install.markdown @@ -16,6 +16,7 @@ Required Packages - [optional] libtbb2 libtbb-dev - [optional] libdc1394 2.x - [optional] libjpeg-dev, libpng-dev, libtiff-dev, libjasper-dev, libdc1394-22-dev +- [optional] CUDA Toolkit 6.5 or higher The packages can be installed using a terminal and the following commands or by using Synaptic Manager: From 4423a5edada0accf4bac71d76365feab8aeb1df6 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Sat, 23 Jul 2016 23:11:57 +0900 Subject: [PATCH 100/153] fix build error * NAN is not defined on some platform --- modules/core/test/test_arithm.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 1289b73e39..f946b7b8bc 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1902,6 +1902,11 @@ TEST(Normalize, regression_5876_inplace_change_type) EXPECT_EQ(0, cvtest::norm(m, result, NORM_INF)); } +#ifndef NAN +#include // numeric_limits::quiet_NaN() +#define NAN std::numeric_limits::quiet_NaN() +#endif + TEST(MinMaxLoc, regression_4955_nans) { cv::Mat one_mat(2, 2, CV_32F, cv::Scalar(1)); From d394d26b46ba6d995e9291492bb6d94da78c0be5 Mon Sep 17 00:00:00 2001 From: Alexandr Kondratev Date: Sat, 23 Jul 2016 18:06:46 +0300 Subject: [PATCH 101/153] highgui: window QT+OpenGL mouse wheel support, build fix --- modules/highgui/src/window_QT.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 76900388fe..f0b06578f4 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -2637,9 +2637,6 @@ void DefaultViewPort::wheelEvent(QWheelEvent* evnt) icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags); icvmouseProcessing(QPointF(pt), cv_event, flags); - scaleView(delta / 240.0, pt); - viewport()->update(); - QWidget::wheelEvent(evnt); } From 70dcd107d08a2e6bf80a4b625c12df7533b8d211 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Sun, 24 Jul 2016 23:34:12 +0900 Subject: [PATCH 102/153] follow the comment * test build on VS2012 --- modules/core/test/test_arithm.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index f946b7b8bc..68aa09b0ed 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1,4 +1,5 @@ #include "test_precomp.hpp" +#include using namespace cv; using namespace std; @@ -1902,11 +1903,6 @@ TEST(Normalize, regression_5876_inplace_change_type) EXPECT_EQ(0, cvtest::norm(m, result, NORM_INF)); } -#ifndef NAN -#include // numeric_limits::quiet_NaN() -#define NAN std::numeric_limits::quiet_NaN() -#endif - TEST(MinMaxLoc, regression_4955_nans) { cv::Mat one_mat(2, 2, CV_32F, cv::Scalar(1)); From 891c83ff35b29e7d4d79d52eb9ff075edadfc51a Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 25 Jul 2016 08:27:52 +0900 Subject: [PATCH 103/153] fix build error * NAN is not defined on some platform * follow the comment on PR --- modules/core/test/test_arithm.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 68aa09b0ed..3264710807 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1,5 +1,9 @@ #include "test_precomp.hpp" #include +#ifndef NAN +#include // numeric_limits::quiet_NaN() +#define NAN std::numeric_limits::quiet_NaN() +#endif using namespace cv; using namespace std; From 0df9cbc954c61fca0993b563c2686f9710978b08 Mon Sep 17 00:00:00 2001 From: Thierry Fauck Date: Mon, 25 Jul 2016 11:30:50 +0200 Subject: [PATCH 104/153] Non existent definition of _FPU_EXTENDED definition prevent compilation when WITH_CUDA set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Non existence of _FPU_EXTENDED definition on powerpc64 (like it is for apple and arm) prevent compilation when WITH_CUDA is set. Adding powerpc64 as case to not use these definitions modifié: modules/cudalegacy/test/TestHaarCascadeApplication.cpp modifié: modules/cudalegacy/test/test_precomp.hpp Signed-off-by: Thierry Fauck --- modules/cudalegacy/test/TestHaarCascadeApplication.cpp | 9 ++++++--- modules/cudalegacy/test/test_precomp.hpp | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/cudalegacy/test/TestHaarCascadeApplication.cpp b/modules/cudalegacy/test/TestHaarCascadeApplication.cpp index b7c389e558..603f109c86 100644 --- a/modules/cudalegacy/test/TestHaarCascadeApplication.cpp +++ b/modules/cudalegacy/test/TestHaarCascadeApplication.cpp @@ -52,7 +52,8 @@ namespace ~FpuControl(); private: - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && + !defined(__aarch64__) && !defined(__powerpc64__) fpu_control_t fpu_oldcw, fpu_cw; #elif defined(_WIN32) && !defined(_WIN64) unsigned int fpu_oldcw, fpu_cw; @@ -61,7 +62,8 @@ namespace FpuControl::FpuControl() { - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && + !defined(__aarch64__) && !defined(__powerpc64__) _FPU_GETCW(fpu_oldcw); fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE & ~_FPU_SINGLE) | _FPU_SINGLE; _FPU_SETCW(fpu_cw); @@ -74,7 +76,8 @@ namespace FpuControl::~FpuControl() { - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && + !defined(__aarch64__) && !defined(__powerpc64__) _FPU_SETCW(fpu_oldcw); #elif defined(_WIN32) && !defined(_WIN64) _controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC); diff --git a/modules/cudalegacy/test/test_precomp.hpp b/modules/cudalegacy/test/test_precomp.hpp index 41314da525..eeebb743f0 100644 --- a/modules/cudalegacy/test/test_precomp.hpp +++ b/modules/cudalegacy/test/test_precomp.hpp @@ -51,7 +51,8 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ -#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) +#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && + !defined(__aarch64__) && !defined(__powerpc64__) #include #endif From 31fb82176dca5aa6fa47a802988f16bb3de1efb6 Mon Sep 17 00:00:00 2001 From: Oskari Vinko Date: Mon, 25 Jul 2016 20:25:38 +0200 Subject: [PATCH 105/153] Corrected tutorial grammar and sentences --- .../py_features_meaning.markdown | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/py_tutorials/py_feature2d/py_features_meaning/py_features_meaning.markdown b/doc/py_tutorials/py_feature2d/py_features_meaning/py_features_meaning.markdown index 79d09c5fe2..166ffba4a1 100644 --- a/doc/py_tutorials/py_feature2d/py_features_meaning/py_features_meaning.markdown +++ b/doc/py_tutorials/py_feature2d/py_features_meaning/py_features_meaning.markdown @@ -22,61 +22,61 @@ Well, the questions and imaginations continue. But it all depends on the most ba you play jigsaw puzzles? How do you arrange lots of scrambled image pieces into a big single image? How can you stitch a lot of natural images to a single image? -The answer is, we are looking for specific patterns or specific features which are unique, which can -be easily tracked, which can be easily compared. If we go for a definition of such a feature, we may -find it difficult to express it in words, but we know what are they. If some one asks you to point +The answer is, we are looking for specific patterns or specific features which are unique, can +be easily tracked and can be easily compared. If we go for a definition of such a feature, we may +find it difficult to express it in words, but we know what they are. If someone asks you to point out one good feature which can be compared across several images, you can point out one. That is -why, even small children can simply play these games. We search for these features in an image, we -find them, we find the same features in other images, we align them. That's it. (In jigsaw puzzle, +why even small children can simply play these games. We search for these features in an image, +find them, look for the same features in other images and align them. That's it. (In jigsaw puzzle, we look more into continuity of different images). All these abilities are present in us inherently. So our one basic question expands to more in number, but becomes more specific. **What are these -features?**. *(The answer should be understandable to a computer also.)* +features?**. (The answer should be understandable also to a computer.) -Well, it is difficult to say how humans find these features. It is already programmed in our brain. +It is difficult to say how humans find these features. This is already programmed in our brain. But if we look deep into some pictures and search for different patterns, we will find something interesting. For example, take below image: ![image](images/feature_building.jpg) -Image is very simple. At the top of image, six small image patches are given. Question for you is to -find the exact location of these patches in the original image. How many correct results you can -find ? +The image is very simple. At the top of image, six small image patches are given. Question for you is to +find the exact location of these patches in the original image. How many correct results can you +find? -A and B are flat surfaces, and they are spread in a lot of area. It is difficult to find the exact +A and B are flat surfaces and they are spread over a lot of area. It is difficult to find the exact location of these patches. -C and D are much more simpler. They are edges of the building. You can find an approximate location, -but exact location is still difficult. It is because, along the edge, it is same everywhere. Normal -to the edge, it is different. So edge is a much better feature compared to flat area, but not good -enough (It is good in jigsaw puzzle for comparing continuity of edges). +C and D are much more simple. They are edges of the building. You can find an approximate location, +but exact location is still difficult. This is because the pattern is same everywhere along the edge. +At the edge, however, it is different. An edge is therefore better feature compared to flat area, but +not good enough (It is good in jigsaw puzzle for comparing continuity of edges). -Finally, E and F are some corners of the building. And they can be easily found out. Because at -corners, wherever you move this patch, it will look different. So they can be considered as a good -feature. So now we move into more simpler (and widely used image) for better understanding. +Finally, E and F are some corners of the building. And they can be easily found. Because at the +corners, wherever you move this patch, it will look different. So they can be considered as good +features. So now we move into simpler (and widely used image) for better understanding. ![image](images/feature_simple.png) -Just like above, blue patch is flat area and difficult to find and track. Wherever you move the blue -patch, it looks the same. For black patch, it is an edge. If you move it in vertical direction (i.e. -along the gradient) it changes. Put along the edge (parallel to edge), it looks the same. And for +Just like above, the blue patch is flat area and difficult to find and track. Wherever you move the blue +patch it looks the same. The black patch has an edge. If you move it in vertical direction (i.e. +along the gradient) it changes. Moved along the edge (parallel to edge), it looks the same. And for red patch, it is a corner. Wherever you move the patch, it looks different, means it is unique. So basically, corners are considered to be good features in an image. (Not just corners, in some cases blobs are considered good features). So now we answered our question, "what are these features?". But next question arises. How do we -find them? Or how do we find the corners?. That also we answered in an intuitive way, i.e., look for +find them? Or how do we find the corners?. We answered that in an intuitive way, i.e., look for the regions in images which have maximum variation when moved (by a small amount) in all regions around it. This would be projected into computer language in coming chapters. So finding these image features is called **Feature Detection**. -So we found the features in image (Assume you did it). Once you found it, you should find the same -in the other images. What we do? We take a region around the feature, we explain it in our own -words, like "upper part is blue sky, lower part is building region, on that building there are some -glasses etc" and you search for the same area in other images. Basically, you are describing the -feature. Similar way, computer also should describe the region around the feature so that it can +We found the features in the images. Once you have found it, you should be able to find the same +in the other images. How is this done? We take a region around the feature, we explain it in our own +words, like "upper part is blue sky, lower part is region from a building, on that building there is +glass etc" and you search for the same area in the other images. Basically, you are describing the +feature. Similarly, a computer also should describe the region around the feature so that it can find it in other images. So called description is called **Feature Description**. Once you have the -features and its description, you can find same features in all images and align them, stitch them +features and its description, you can find same features in all images and align them, stitch them together or do whatever you want. So in this module, we are looking to different algorithms in OpenCV to find features, describe them, From ce66de8e3dfad38860191a0973fab6d3d1e5ac78 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Tue, 26 Jul 2016 12:56:10 +0900 Subject: [PATCH 106/153] calib3d: fix typo --- modules/calib3d/src/solvepnp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index 23575199d9..12dcb4a6ca 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -158,7 +158,7 @@ public: rvec(_rvec), tvec(_tvec) {} /* Pre: True */ - /* Post: compute _model with given points an return number of found models */ + /* Post: compute _model with given points and return number of found models */ int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const { Mat opoints = _m1.getMat(), ipoints = _m2.getMat(); From 72672c293f9b81783bf3c7bc4bcb2a7787e3b226 Mon Sep 17 00:00:00 2001 From: Matthew Self Date: Mon, 25 Jul 2016 21:17:54 -0700 Subject: [PATCH 107/153] Make goodFeaturesToTrack() return deterministic results When using OCL, the results of goodFeaturesToTrack() vary slightly from run to run. This appears to be because the order of the results from the findCorners kernel depends on thread execution and the sorting function that is used at the end to rank the features only enforces are partial sort order. This does not materially impact the quality of the results, but it makes it hard to build regression tests and generally introduces noise into the system that should be avoided. An easy fix is to change the sort function to enforce a total sort on the features, even in cases where the match quality is exactly the same for two features. --- modules/imgproc/src/featureselect.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 2921d3c115..2f5f1631de 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -54,7 +54,8 @@ struct greaterThanPtr : public std::binary_function { bool operator () (const float * a, const float * b) const - { return *a > *b; } + // Ensure a fully deterministic result of the sort + { return (*a > *b) ? true : (*a < *b) ? false : (a > b); } }; #ifdef HAVE_OPENCL @@ -66,7 +67,8 @@ struct Corner short x; bool operator < (const Corner & c) const - { return val > c.val; } + // Ensure a fully deterministic result of the sort + { return (val > c.val) ? true : (val < c.val) ? false : (y > c.y) ? true : (y < c.y) ? false : (x > c.x); } }; static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, From e072fa8121f530dd175fcfed99565064d5ab3bcb Mon Sep 17 00:00:00 2001 From: Julien Dehos Date: Tue, 26 Jul 2016 18:01:36 +0200 Subject: [PATCH 108/153] fix a bug in MergeDebevec (modify input times) --- modules/photo/src/merge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/photo/src/merge.cpp b/modules/photo/src/merge.cpp index 4292f7c1b3..9772212d7b 100644 --- a/modules/photo/src/merge.cpp +++ b/modules/photo/src/merge.cpp @@ -85,7 +85,7 @@ public: CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 && log_response.channels() == channels); - Mat exp_values(times); + Mat exp_values(times.clone()); log(exp_values, exp_values); result = Mat::zeros(size, CV_32FCC); From c6f790ce12966850b0a40c8ba73f547afeae7bfe Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 26 Jul 2016 23:29:05 -0300 Subject: [PATCH 109/153] Fixed using local variable instead of global var. - Still need to change SSE_2 --- modules/calib3d/src/stereobm.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 98a4d69393..58de587727 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -338,7 +338,7 @@ static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right, int ftzero = state.preFilterCap; int textureThreshold = state.textureThreshold; int uniquenessRatio = state.uniquenessRatio; - short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT); + short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT_16S); ushort *sad, *hsad0, *hsad, *hsad_sub; int *htext; @@ -1096,7 +1096,14 @@ public: if( params.uniquenessRatio < 0 ) CV_Error( Error::StsOutOfRange, "uniqueness ratio must be non-negative" ); - int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT; + int disp_shift; + if (dtype == CV_16SC1) + disp_shift = DISPARITY_SHIFT_16S; + else + disp_shift = DISPARITY_SHIFT_32S; + + + int FILTERED = (params.minDisparity - 1) << disp_shift; #ifdef HAVE_OPENCL if(ocl::useOpenCL() && disparr.isUMat() && params.textureThreshold == 0) @@ -1109,7 +1116,7 @@ public: if( params.speckleRange >= 0 && params.speckleWindowSize > 0 ) filterSpeckles(disparr.getMat(), FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); if (dtype == CV_32F) - disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << DISPARITY_SHIFT), 0); + disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << disp_shift), 0); CV_IMPL_ADD(CV_IMPL_OCL); return; } @@ -1138,7 +1145,7 @@ public: if( lofs >= width || rofs >= width || width1 < 1 ) { - disp0 = Scalar::all( FILTERED * ( disp0.type() < CV_32F ? 1 : 1./(1 << DISPARITY_SHIFT) ) ); + disp0 = Scalar::all( FILTERED * ( disp0.type() < CV_32F ? 1 : 1./(1 << disp_shift) ) ); return; } @@ -1194,7 +1201,7 @@ public: filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); if (disp0.data != disp.data) - disp.convertTo(disp0, disp0.type(), 1./(1 << DISPARITY_SHIFT), 0); + disp.convertTo(disp0, disp0.type(), 1./(1 << disp_shift), 0); } int getMinDisparity() const { return params.minDisparity; } From 718891d9377dd09bc7e16e4d3430c8b934ca0602 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 26 Jul 2016 23:46:58 -0300 Subject: [PATCH 110/153] Tabs -> Whitespaces. --- modules/calib3d/src/stereobm.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 58de587727..c4278b3617 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -1096,14 +1096,14 @@ public: if( params.uniquenessRatio < 0 ) CV_Error( Error::StsOutOfRange, "uniqueness ratio must be non-negative" ); - int disp_shift; - if (dtype == CV_16SC1) - disp_shift = DISPARITY_SHIFT_16S; - else - disp_shift = DISPARITY_SHIFT_32S; + int disp_shift; + if (dtype == CV_16SC1) + disp_shift = DISPARITY_SHIFT_16S; + else + disp_shift = DISPARITY_SHIFT_32S; - int FILTERED = (params.minDisparity - 1) << disp_shift; + int FILTERED = (params.minDisparity - 1) << disp_shift; #ifdef HAVE_OPENCL if(ocl::useOpenCL() && disparr.isUMat() && params.textureThreshold == 0) @@ -1116,7 +1116,7 @@ public: if( params.speckleRange >= 0 && params.speckleWindowSize > 0 ) filterSpeckles(disparr.getMat(), FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); if (dtype == CV_32F) - disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << disp_shift), 0); + disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << disp_shift), 0); CV_IMPL_ADD(CV_IMPL_OCL); return; } @@ -1145,7 +1145,7 @@ public: if( lofs >= width || rofs >= width || width1 < 1 ) { - disp0 = Scalar::all( FILTERED * ( disp0.type() < CV_32F ? 1 : 1./(1 << disp_shift) ) ); + disp0 = Scalar::all( FILTERED * ( disp0.type() < CV_32F ? 1 : 1./(1 << disp_shift) ) ); return; } @@ -1201,7 +1201,7 @@ public: filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); if (disp0.data != disp.data) - disp.convertTo(disp0, disp0.type(), 1./(1 << disp_shift), 0); + disp.convertTo(disp0, disp0.type(), 1./(1 << disp_shift), 0); } int getMinDisparity() const { return params.minDisparity; } From 64dbf6c987f8197406020ef1defc7a46f78fb73f Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Wed, 27 Jul 2016 11:21:08 +0200 Subject: [PATCH 111/153] fix build #6993 --- modules/cudalegacy/test/TestHaarCascadeApplication.cpp | 9 +++------ modules/cudalegacy/test/test_precomp.hpp | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/cudalegacy/test/TestHaarCascadeApplication.cpp b/modules/cudalegacy/test/TestHaarCascadeApplication.cpp index 603f109c86..adc3dffa18 100644 --- a/modules/cudalegacy/test/TestHaarCascadeApplication.cpp +++ b/modules/cudalegacy/test/TestHaarCascadeApplication.cpp @@ -52,8 +52,7 @@ namespace ~FpuControl(); private: - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && - !defined(__aarch64__) && !defined(__powerpc64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__) fpu_control_t fpu_oldcw, fpu_cw; #elif defined(_WIN32) && !defined(_WIN64) unsigned int fpu_oldcw, fpu_cw; @@ -62,8 +61,7 @@ namespace FpuControl::FpuControl() { - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && - !defined(__aarch64__) && !defined(__powerpc64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__) _FPU_GETCW(fpu_oldcw); fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE & ~_FPU_SINGLE) | _FPU_SINGLE; _FPU_SETCW(fpu_cw); @@ -76,8 +74,7 @@ namespace FpuControl::~FpuControl() { - #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && - !defined(__aarch64__) && !defined(__powerpc64__) + #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__) _FPU_SETCW(fpu_oldcw); #elif defined(_WIN32) && !defined(_WIN64) _controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC); diff --git a/modules/cudalegacy/test/test_precomp.hpp b/modules/cudalegacy/test/test_precomp.hpp index eeebb743f0..5e0e9ee283 100644 --- a/modules/cudalegacy/test/test_precomp.hpp +++ b/modules/cudalegacy/test/test_precomp.hpp @@ -51,8 +51,7 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ -#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && - !defined(__aarch64__) && !defined(__powerpc64__) +#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__) #include #endif From 6df12a0507dbe818b4b9da80cf74ef684b149cc8 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Wed, 27 Jul 2016 11:39:50 +0200 Subject: [PATCH 112/153] add limits of tool to help message --- apps/visualisation/opencv_visualisation.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/visualisation/opencv_visualisation.cpp b/apps/visualisation/opencv_visualisation.cpp index 75703bd528..68ebd65902 100644 --- a/apps/visualisation/opencv_visualisation.cpp +++ b/apps/visualisation/opencv_visualisation.cpp @@ -49,13 +49,6 @@ understanding of the used features. USAGE: ./opencv_visualisation --model= --image= --data=