From 05fbd1e5bc4500cf3b96319a41d3298534d72070 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Mon, 22 Jun 2020 22:53:05 +0200 Subject: [PATCH 1/9] DNA mode: add the distance computations --- modules/flann/include/opencv2/flann.hpp | 10 ++ modules/flann/include/opencv2/flann/defines.h | 1 + modules/flann/include/opencv2/flann/dist.h | 151 ++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/modules/flann/include/opencv2/flann.hpp b/modules/flann/include/opencv2/flann.hpp index e8ee91a3ec..5c52bfeeb5 100644 --- a/modules/flann/include/opencv2/flann.hpp +++ b/modules/flann/include/opencv2/flann.hpp @@ -95,6 +95,8 @@ using ::cvflann::MaxDistance; using ::cvflann::HammingLUT; using ::cvflann::Hamming; using ::cvflann::Hamming2; +using ::cvflann::DNAmmingLUT; +using ::cvflann::DNAmming2; using ::cvflann::HistIntersectionDistance; using ::cvflann::HellingerDistance; using ::cvflann::ChiSquareDistance; @@ -131,6 +133,14 @@ performed using library calls, if available. Lookup table implementation is used cv::flann::Hamming2 - %Hamming distance functor. Population count is implemented in 12 arithmetic operations (one of which is multiplication). +cv::flann::DNAmmingLUT - %Adaptation of the Hamming distance functor to DNA comparison. +As the four bases A, C, G, T of the DNA (or A, G, C, U for RNA) can be coded on 2 bits, +it counts the bits pairs differences between two sequences using a lookup table implementation. + +cv::flann::DNAmming2 - %Adaptation of the Hamming distance functor to DNA comparison. +Bases differences count are vectorised thanks to arithmetic operations using standard +registers (AVX2 and AVX-512 should come in a near future). + cv::flann::HistIntersectionDistance - The histogram intersection distance functor. diff --git a/modules/flann/include/opencv2/flann/defines.h b/modules/flann/include/opencv2/flann/defines.h index 884c6004d4..8ab83293ff 100644 --- a/modules/flann/include/opencv2/flann/defines.h +++ b/modules/flann/include/opencv2/flann/defines.h @@ -128,6 +128,7 @@ enum flann_distance_t FLANN_DIST_KULLBACK_LEIBLER = 8, FLANN_DIST_KL = 8, FLANN_DIST_HAMMING = 9, + FLANN_DIST_DNAMMING = 10, // deprecated constants, should use the FLANN_DIST_* ones instead EUCLIDEAN = 1, diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index e41b994d7e..97daa55cd9 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -744,6 +744,157 @@ private: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +struct DNAmmingLUT +{ + typedef False is_kdtree_distance; + typedef False is_vector_space_distance; + + typedef unsigned char ElementType; + typedef int ResultType; + typedef ElementType CentersType; + + /** this will count the bits in a ^ b + */ + template + ResultType operator()(const unsigned char* a, const Iterator2 b, size_t size) const + { + static const uchar popCountTable[] = + { + 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4 + }; + ResultType result = 0; + const unsigned char* b2 = reinterpret_cast (b); + for (size_t i = 0; i < size; i++) { + result += popCountTable[a[i] ^ b2[i]]; + } + return result; + } + + + ResultType operator()(const unsigned char* a, const ZeroIterator b, size_t size) const + { + (void)b; + static const uchar popCountTable[] = + { + 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4 + }; + ResultType result = 0; + for (size_t i = 0; i < size; i++) { + result += popCountTable[a[i]]; + } + return result; + } +}; + + +template +struct DNAmming2 +{ + typedef False is_kdtree_distance; + typedef False is_vector_space_distance; + + typedef T ElementType; + typedef int ResultType; + typedef ElementType CentersType; + + /** This is popcount_3() from: + * http://en.wikipedia.org/wiki/Hamming_weight */ + unsigned int popcnt32(uint32_t n) const + { + n = ((n >> 1) | n) & 0x55555555; + n = (n & 0x33333333) + ((n >> 2) & 0x33333333); + return (((n + (n >> 4))& 0x0F0F0F0F)* 0x01010101) >> 24; + } + +#ifdef FLANN_PLATFORM_64_BIT + unsigned int popcnt64(uint64_t n) const + { + n = ((n >> 1) | n) & 0x5555555555555555; + n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333); + return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0f)* 0x0101010101010101) >> 56; + } +#endif + + template + ResultType operator()(const Iterator1 a, const Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const + { + CV_DbgAssert(!(size % long_word_size_) && "vectors size must be multiple of long words size (i.e. 8)"); + +#ifdef FLANN_PLATFORM_64_BIT + const uint64_t* pa = reinterpret_cast(a); + const uint64_t* pb = reinterpret_cast(b); + ResultType result = 0; + size /= long_word_size_; + for(size_t i = 0; i < size; ++i ) { + result += popcnt64(*pa ^ *pb); + ++pa; + ++pb; + } +#else + const uint32_t* pa = reinterpret_cast(a); + const uint32_t* pb = reinterpret_cast(b); + ResultType result = 0; + size /= long_word_size_; + for(size_t i = 0; i < size; ++i ) { + result += popcnt32(*pa ^ *pb); + ++pa; + ++pb; + } +#endif + return result; + } + + + template + ResultType operator()(const Iterator1 a, ZeroIterator b, size_t size, ResultType /*worst_dist*/ = -1) const + { + CV_DbgAssert(!(size % long_word_size_) && "vectors size must be multiple of long words size (i.e. 8)"); + + (void)b; +#ifdef FLANN_PLATFORM_64_BIT + const uint64_t* pa = reinterpret_cast(a); + ResultType result = 0; + size /= long_word_size_; + for(size_t i = 0; i < size; ++i ) { + result += popcnt64(*pa); + ++pa; + } +#else + const uint32_t* pa = reinterpret_cast(a); + ResultType result = 0; + size /= long_word_size_; + for(size_t i = 0; i < size; ++i ) { + result += popcnt32(*pa); + ++pa; + } +#endif + return result; + } + +private: +#ifdef FLANN_PLATFORM_64_BIT + static const size_t long_word_size_= sizeof(uint64_t)/sizeof(unsigned char); +#else + static const size_t long_word_size_= sizeof(uint32_t)/sizeof(unsigned char); +#endif +}; + + + template struct HistIntersectionDistance { From 613ff61de78959d0124e76de7b1495b2b93c5420 Mon Sep 17 00:00:00 2001 From: kadi soheib Date: Sun, 2 Aug 2020 22:49:46 +0300 Subject: [PATCH 2/9] Added reference to paper. --- doc/opencv.bib | 7 +++++++ modules/imgproc/include/opencv2/imgproc.hpp | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/opencv.bib b/doc/opencv.bib index bdfbc8cf1e..974514b2eb 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -1228,3 +1228,10 @@ number={2}, pages={117-135}, } +@inproceedings{forstner1987fast, + title={A fast operator for detection and precise location of distincs points, corners and center of circular features}, + author={FORSTNER, W}, + booktitle={Proc. of the Intercommission Conference on Fast Processing of Photogrammetric Data, Interlaken, Switzerland, 1987}, + pages={281--305}, + year={1987} +} diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 962501b62d..82e1d24eae 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1861,8 +1861,8 @@ CV_EXPORTS_W void preCornerDetect( InputArray src, OutputArray dst, int ksize, /** @brief Refines the corner locations. -The function iterates to find the sub-pixel accurate location of corners or radial saddle points, as -shown on the figure below. +The function iterates to find the sub-pixel accurate location of corners or radial saddle +points as described in @cite forstner1987fast, and as shown on the figure below. ![image](pics/cornersubpix.png) From 3f55152ca093edd90eba6cd2c979db0f32468900 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Wed, 12 Aug 2020 23:07:35 +0200 Subject: [PATCH 3/9] Add debug assert to check in FLANN the vectors size is multiple of the architecture word size --- modules/flann/include/opencv2/flann/dist.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index e41b994d7e..b5a1f22532 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -683,6 +683,8 @@ struct Hamming2 template ResultType operator()(const Iterator1 a, const Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const { + CV_DbgAssert(!(size % long_word_size_) && "vectors size must be multiple of long words size (i.e. 8)"); + #ifdef FLANN_PLATFORM_64_BIT const uint64_t* pa = reinterpret_cast(a); const uint64_t* pb = reinterpret_cast(b); @@ -711,6 +713,8 @@ struct Hamming2 template ResultType operator()(const Iterator1 a, ZeroIterator b, size_t size, ResultType /*worst_dist*/ = -1) const { + CV_DbgAssert(!(size % long_word_size_) && "vectors size must be multiple of long words size (i.e. 8)"); + (void)b; #ifdef FLANN_PLATFORM_64_BIT const uint64_t* pa = reinterpret_cast(a); From cc769ff19ddc742b5341186650c9b19ae4122d61 Mon Sep 17 00:00:00 2001 From: Tomoaki Teshima Date: Mon, 17 Aug 2020 21:24:54 +0900 Subject: [PATCH 4/9] fix build error on odroid-n2-plus --- modules/videoio/src/cap_ffmpeg_impl.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index b5c0824098..ba21428568 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -149,6 +149,8 @@ extern "C" { #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 #define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 #define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8 +#define AV_PIX_FMT_BGRA PIX_FMT_BGRA +#define AV_PIX_FMT_RGBA PIX_FMT_RGBA #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P @@ -356,7 +358,7 @@ struct AVInterruptCallbackMetadata // https://github.com/opencv/opencv/pull/12693#issuecomment-426236731 static -inline const char* _opencv_avcodec_get_name(AVCodecID id) +inline const char* _opencv_avcodec_get_name(CV_CODEC_ID id) { #if LIBAVCODEC_VERSION_MICRO >= 100 \ && LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(53, 47, 100) @@ -1087,11 +1089,11 @@ bool CvCapture_FFMPEG::processRawPacket() { rawModeInitialized = true; #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(58, 20, 100) - AVCodecID eVideoCodec = ic->streams[video_stream]->codecpar->codec_id; + CV_CODEC_ID eVideoCodec = ic->streams[video_stream]->codecpar->codec_id; #elif LIBAVFORMAT_BUILD > 4628 - AVCodecID eVideoCodec = video_st->codec->codec_id; + CV_CODEC_ID eVideoCodec = video_st->codec->codec_id; #else - AVCodecID eVideoCodec = video_st->codec.codec_id; + CV_CODEC_ID eVideoCodec = video_st->codec.codec_id; #endif const char* filterName = NULL; if (eVideoCodec == CV_CODEC(CODEC_ID_H264) @@ -1394,7 +1396,7 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const if( !video_st ) return 0; double codec_tag = 0; - AVCodecID codec_id = AV_CODEC_ID_NONE; + CV_CODEC_ID codec_id = AV_CODEC_ID_NONE; const char* codec_fourcc = NULL; switch( property_id ) @@ -1858,7 +1860,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54,25,0) // Set per-codec defaults - AVCodecID c_id = c->codec_id; + CV_CODEC_ID c_id = c->codec_id; avcodec_get_context_defaults3(c, codec); // avcodec_get_context_defaults3 erases codec_id for some reason c->codec_id = c_id; From ac177b849c2860d7469fcd0dda6edf6a18c997b6 Mon Sep 17 00:00:00 2001 From: danielenricocahall Date: Tue, 4 Aug 2020 22:18:32 -0400 Subject: [PATCH 5/9] Improve initialization performance of Brisk reformatting Improve initialization performance of Brisk fix formatting Improve initialization performance of Brisk formatting Improve initialization performance of Brisk make a lookup table for ring use cosine/sine lookup table for theta in brisk and utilize trig identity fix ring lookup table use cosine/sine lookup table for theta in brisk and utilize trig identity formatting use cosine/sine lookup table for theta in brisk and utilize trig identity move scale radius product to ring loop to ensure it's not recomputed for each rot revert change move scale radius product to ring loop to ensure it's not recomputed for each rot remove rings lookup table move scale radius product to ring loop to ensure it's not recomputed for each rot fix formatting of for loop move scale radius product to ring loop to ensure it's not recomputed for each rot use sine/cosine approximations for brisk lookup table. add documentation for sine/cosine lookup tables Improve initialization performance of BRISK --- modules/features2d/src/brisk.cpp | 94 ++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/modules/features2d/src/brisk.cpp b/modules/features2d/src/brisk.cpp index 4038279d75..98ae1c4f4e 100644 --- a/modules/features2d/src/brisk.cpp +++ b/modules/features2d/src/brisk.cpp @@ -353,13 +353,30 @@ BRISK_Impl::generateKernel(const std::vector &radiusList, const int rings = (int)radiusList.size(); CV_Assert(radiusList.size() != 0 && radiusList.size() == numberList.size()); points_ = 0; // remember the total number of points + double sineThetaLookupTable[n_rot_]; + double cosThetaLookupTable[n_rot_]; for (int ring = 0; ring < rings; ring++) { points_ += numberList[ring]; } + + // using a sine/cosine approximation for the lookup table + // utilizes the trig identities: + // sin(a + b) = sin(a)cos(b) + cos(a)sin(b) + // cos(a + b) = cos(a)cos(b) - sin(a)sin(b) + // and the fact that sin(0) = 0, cos(0) = 1 + double cosval = 1., sinval = 0.; + double dcos = cos(2*CV_PI/double(n_rot_)), dsin = sin(2*CV_PI/double(n_rot_)); + for( size_t rot = 0; rot < n_rot_; ++rot) + { + sineThetaLookupTable[rot] = sinval; + cosThetaLookupTable[rot] = cosval; + double t = sinval*dcos + cosval*dsin; + cosval = cosval*dcos - sinval*dsin; + sinval = t; + } // set up the patterns patternPoints_ = new BriskPatternPoint[points_ * scales_ * n_rot_]; - BriskPatternPoint* patternIterator = patternPoints_; // define the scale discretization: static const float lb_scale = (float)(std::log(scalerange_) / std::log(2.0)); @@ -370,46 +387,51 @@ BRISK_Impl::generateKernel(const std::vector &radiusList, const float sigma_scale = 1.3f; - for (unsigned int scale = 0; scale < scales_; ++scale) - { - scaleList_[scale] = (float)std::pow((double) 2.0, (double) (scale * lb_scale_step)); - sizeList_[scale] = 0; - - // generate the pattern points look-up - double alpha, theta; - for (size_t rot = 0; rot < n_rot_; ++rot) - { - theta = double(rot) * 2 * CV_PI / double(n_rot_); // this is the rotation of the feature - for (int ring = 0; ring < rings; ++ring) - { - for (int num = 0; num < numberList[ring]; ++num) - { - // the actual coordinates on the circle - alpha = (double(num)) * 2 * CV_PI / double(numberList[ring]); - patternIterator->x = (float)(scaleList_[scale] * radiusList[ring] * cos(alpha + theta)); // feature rotation plus angle of the point - patternIterator->y = (float)(scaleList_[scale] * radiusList[ring] * sin(alpha + theta)); - // and the gaussian kernel sigma - if (ring == 0) - { - patternIterator->sigma = sigma_scale * scaleList_[scale] * 0.5f; - } - else - { - patternIterator->sigma = (float)(sigma_scale * scaleList_[scale] * (double(radiusList[ring])) - * sin(CV_PI / numberList[ring])); + for (unsigned int scale = 0; scale < scales_; ++scale) { + scaleList_[scale] = (float) std::pow((double) 2.0, (double) (scale * lb_scale_step)); + sizeList_[scale] = 0; + BriskPatternPoint *patternIteratorOuter = patternPoints_ + (scale * n_rot_ * points_); + // generate the pattern points look-up + for (int ring = 0; ring < rings; ++ring) { + double scaleRadiusProduct = scaleList_[scale] * radiusList[ring]; + float patternSigma = 0.0f; + if (ring == 0) { + patternSigma = sigma_scale * scaleList_[scale] * 0.5f; + } else { + patternSigma = (float) (sigma_scale * scaleList_[scale] * (double(radiusList[ring])) + * sin(CV_PI / numberList[ring])); } // adapt the sizeList if necessary - const unsigned int size = cvCeil(((scaleList_[scale] * radiusList[ring]) + patternIterator->sigma)) + 1; - if (sizeList_[scale] < size) - { - sizeList_[scale] = size; + const unsigned int size = cvCeil(((scaleList_[scale] * radiusList[ring]) + patternSigma)) + 1; + if (sizeList_[scale] < size) { + sizeList_[scale] = size; } + for (int num = 0; num < numberList[ring]; ++num) { + BriskPatternPoint *patternIterator = patternIteratorOuter; + double alpha = (double(num)) * 2 * CV_PI / double(numberList[ring]); + double sine_alpha = sin(alpha); + double cosine_alpha = cos(alpha); - // increment the iterator - ++patternIterator; - } + for (size_t rot = 0; rot < n_rot_; ++rot) { + double cosine_theta = cosThetaLookupTable[rot]; + double sine_theta = sineThetaLookupTable[rot]; + + // the actual coordinates on the circle + // sin(a + b) = sin(a) cos(b) + cos(a) sin(b) + // cos(a + b) = cos(a) cos(b) - sin(a) sin(b) + patternIterator->x = (float) (scaleRadiusProduct * + (cosine_theta * cosine_alpha - + sine_theta * sine_alpha)); // feature rotation plus angle of the point + patternIterator->y = (float) (scaleRadiusProduct * + (sine_theta * cosine_alpha + cosine_theta * sine_alpha)); + patternIterator->sigma = patternSigma; + // and the gaussian kernel sigma + // increment the iterator + patternIterator += points_; + } + ++patternIteratorOuter; + } } - } } // now also generate pairings From 6d1f7c2b1b5de024083ca1c3cf515e9d48cd9fb4 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Tue, 18 Aug 2020 16:10:56 +0200 Subject: [PATCH 6/9] Update the stereo sample: * add the HH4 mode * option to display disparity with a color map * display current settings in the title bar * don't close app when wanting to take screenshots --- samples/cpp/stereo_match.cpp | 65 +++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/samples/cpp/stereo_match.cpp b/samples/cpp/stereo_match.cpp index 0cfaba6f70..55cd89c26e 100644 --- a/samples/cpp/stereo_match.cpp +++ b/samples/cpp/stereo_match.cpp @@ -14,15 +14,16 @@ #include "opencv2/core/utility.hpp" #include +#include using namespace cv; static void print_help(char** argv) { printf("\nDemo stereo matching converting L and R images into disparity and point clouds\n"); - printf("\nUsage: %s [--algorithm=bm|sgbm|hh|sgbm3way] [--blocksize=]\n" + printf("\nUsage: %s [--algorithm=bm|sgbm|hh|hh4|sgbm3way] [--blocksize=]\n" "[--max-disparity=] [--scale=scale_factor>] [-i=] [-e=]\n" - "[--no-display] [-o=] [-p=]\n", argv[0]); + "[--no-display] [--color] [-o=] [-p=]\n", argv[0]); } static void saveXYZ(const char* filename, const Mat& mat) @@ -50,16 +51,17 @@ int main(int argc, char** argv) std::string disparity_filename = ""; std::string point_cloud_filename = ""; - enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3, STEREO_3WAY=4 }; + enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3, STEREO_3WAY=4, STEREO_HH4=5 }; int alg = STEREO_SGBM; int SADWindowSize, numberOfDisparities; bool no_display; + bool color_display; float scale; Ptr bm = StereoBM::create(16,9); Ptr sgbm = StereoSGBM::create(0,16,3); cv::CommandLineParser parser(argc, argv, - "{@arg1||}{@arg2||}{help h||}{algorithm||}{max-disparity|0|}{blocksize|0|}{no-display||}{scale|1|}{i||}{e||}{o||}{p||}"); + "{@arg1||}{@arg2||}{help h||}{algorithm||}{max-disparity|0|}{blocksize|0|}{no-display||}{color||}{scale|1|}{i||}{e||}{o||}{p||}"); if(parser.has("help")) { print_help(argv); @@ -74,12 +76,14 @@ int main(int argc, char** argv) _alg == "sgbm" ? STEREO_SGBM : _alg == "hh" ? STEREO_HH : _alg == "var" ? STEREO_VAR : + _alg == "hh4" ? STEREO_HH4 : _alg == "sgbm3way" ? STEREO_3WAY : -1; } numberOfDisparities = parser.get("max-disparity"); SADWindowSize = parser.get("blocksize"); scale = parser.get("scale"); no_display = parser.has("no-display"); + color_display = parser.has("color"); if( parser.has("i") ) intrinsic_filename = parser.get("i"); if( parser.has("e") ) @@ -238,6 +242,8 @@ int main(int argc, char** argv) sgbm->setMode(StereoSGBM::MODE_HH); else if(alg==STEREO_SGBM) sgbm->setMode(StereoSGBM::MODE_SGBM); + else if(alg==STEREO_HH4) + sgbm->setMode(StereoSGBM::MODE_HH4); else if(alg==STEREO_3WAY) sgbm->setMode(StereoSGBM::MODE_SGBM_3WAY); @@ -254,7 +260,7 @@ int main(int argc, char** argv) if (disp.type() == CV_16S) disparity_multiplier = 16.0f; } - else if( alg == STEREO_SGBM || alg == STEREO_HH || alg == STEREO_3WAY ) + else if( alg == STEREO_SGBM || alg == STEREO_HH || alg == STEREO_HH4 || alg == STEREO_3WAY ) { sgbm->compute(img1, img2, disp); if (disp.type() == CV_16S) @@ -268,22 +274,13 @@ int main(int argc, char** argv) disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.)); else disp.convertTo(disp8, CV_8U); - if( !no_display ) - { - namedWindow("left", 1); - imshow("left", img1); - namedWindow("right", 1); - imshow("right", img2); - namedWindow("disparity", 0); - imshow("disparity", disp8); - printf("press any key to continue..."); - fflush(stdout); - waitKey(); - printf("\n"); - } + + Mat disp8_3c; + if (color_display) + cv::applyColorMap(disp8, disp8_3c, COLORMAP_TURBO); if(!disparity_filename.empty()) - imwrite(disparity_filename, disp8); + imwrite(disparity_filename, color_display ? disp8_3c : disp8); if(!point_cloud_filename.empty()) { @@ -297,5 +294,35 @@ int main(int argc, char** argv) printf("\n"); } + if( !no_display ) + { + std::ostringstream oss; + oss << "disparity " << (alg==STEREO_BM ? "bm" : + alg==STEREO_SGBM ? "sgbm" : + alg==STEREO_HH ? "hh" : + alg==STEREO_VAR ? "var" : + alg==STEREO_HH4 ? "hh4" : + alg==STEREO_3WAY ? "sgbm3way" : ""); + oss << " blocksize:" << (alg==STEREO_BM ? SADWindowSize : sgbmWinSize); + oss << " max-disparity:" << numberOfDisparities; + std::string disp_name = oss.str(); + + namedWindow("left", cv::WINDOW_NORMAL); + imshow("left", img1); + namedWindow("right", cv::WINDOW_NORMAL); + imshow("right", img2); + namedWindow(disp_name, cv::WINDOW_AUTOSIZE); + imshow(disp_name, color_display ? disp8_3c : disp8); + + printf("press ESC key or CTRL+C to close..."); + fflush(stdout); + printf("\n"); + while(1) + { + if(waitKey() == 27) //ESC (prevents closing on actions like taking screenshots) + break; + } + } + return 0; } From b3755e617c65efd595c4ca033ae6f2d4e62d75ae Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 20 Aug 2020 19:05:50 +0000 Subject: [PATCH 7/9] ocl: silence warning in case of async cleanup - OpenCL kernel cleanup processing is asynchronous and can be called even after forced clFinish() - buffers are released later in asynchronous mode - silence these false positive cases for asynchronous cleanup --- modules/core/src/umatrix.cpp | 3 ++- modules/core/test/test_umat.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 58f1f909d5..9fe8122d22 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -80,6 +80,7 @@ UMatData::~UMatData() CV_Assert(mapcount == 0); data = origdata = 0; size = 0; + bool isAsyncCleanup = !!(flags & UMatData::ASYNC_CLEANUP); flags = 0; handle = 0; userdata = 0; @@ -106,7 +107,7 @@ UMatData::~UMatData() showWarn = true; if (zero_Ref && zero_URef) // oops, we need to free resources { - showWarn = true; + showWarn = !isAsyncCleanup; // simulate UMat::deallocate u->currAllocator->deallocate(u); } diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index d25916c18a..c2bd6eceba 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -1154,6 +1154,30 @@ TEST(UMat, map_unmap_counting) } +static void process_with_async_cleanup(Mat& frame) +{ + UMat blurResult; + { + UMat umat_buffer = frame.getUMat(ACCESS_READ); + cv::blur(umat_buffer, blurResult, Size(3, 3)); // UMat doesn't support inplace, this call is not synchronized + } + Mat result; + blurResult.copyTo(result); + swap(result, frame); + // umat_buffer cleanup is done asynchronously, silence warning about original 'frame' cleanup here (through 'result') + // - release input 'frame' (as 'result') + // - release 'umat_buffer' asynchronously and silence warning about "parent" buffer (in debug builds) +} +TEST(UMat, async_cleanup_without_call_chain_warning) +{ + Mat frame(Size(640, 480), CV_8UC1, Scalar::all(128)); + for (int i = 0; i < 10; i++) + { + process_with_async_cleanup(frame); + } +} + + ///////////// oclCleanupCallback threadsafe check (#5062) ///////////////////// // Case 1: reuse of old src Mat in OCL pipe. Hard to catch! From cd00d8f3f0c0a8bdd13bdd38453497deae0b6952 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 20 Aug 2020 21:43:14 +0000 Subject: [PATCH 8/9] core(trace): lazy quering for OPENCV_TRACE_LOCATION - fixes proper initialization of non-trivial variable --- modules/core/src/trace.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/core/src/trace.cpp b/modules/core/src/trace.cpp index c316737b13..1c12c2a2e5 100644 --- a/modules/core/src/trace.cpp +++ b/modules/core/src/trace.cpp @@ -82,7 +82,12 @@ static bool getParameterTraceEnable() static int param_maxRegionDepthOpenCV = (int)utils::getConfigurationParameterSizeT("OPENCV_TRACE_DEPTH_OPENCV", 1); static int param_maxRegionChildrenOpenCV = (int)utils::getConfigurationParameterSizeT("OPENCV_TRACE_MAX_CHILDREN_OPENCV", 1000); static int param_maxRegionChildren = (int)utils::getConfigurationParameterSizeT("OPENCV_TRACE_MAX_CHILDREN", 10000); -static cv::String param_traceLocation = utils::getConfigurationParameterString("OPENCV_TRACE_LOCATION", "OpenCVTrace"); + +static const cv::String& getParameterTraceLocation() +{ + static cv::String param_traceLocation = utils::getConfigurationParameterString("OPENCV_TRACE_LOCATION", "OpenCVTrace"); + return param_traceLocation; +} #ifdef HAVE_OPENCL static bool param_synchronizeOpenCL = utils::getConfigurationParameterBool("OPENCV_TRACE_SYNC_OPENCL", false); @@ -813,7 +818,7 @@ TraceStorage* TraceManagerThreadLocal::getStorage() const TraceStorage* global = getTraceManager().trace_storage.get(); if (global) { - const std::string filepath = cv::format("%s-%03d.txt", param_traceLocation.c_str(), threadID).c_str(); + const std::string filepath = cv::format("%s-%03d.txt", getParameterTraceLocation().c_str(), threadID).c_str(); TraceMessage msg; const char* pos = strrchr(filepath.c_str(), '/'); // extract filename #ifdef _WIN32 @@ -848,7 +853,7 @@ TraceManager::TraceManager() activated = getParameterTraceEnable(); if (activated) - trace_storage.reset(new SyncTraceStorage(std::string(param_traceLocation) + ".txt")); + trace_storage.reset(new SyncTraceStorage(std::string(getParameterTraceLocation()) + ".txt")); #ifdef OPENCV_WITH_ITT if (isITTEnabled()) From 885fb703cf5605d8d7e95396939d87ddedcb6fae Mon Sep 17 00:00:00 2001 From: Anna Petrovicheva Date: Wed, 19 Aug 2020 15:46:55 +0300 Subject: [PATCH 9/9] Added a note about OpenCV logo --- doc/opencv-logo.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/opencv-logo.md diff --git a/doc/opencv-logo.md b/doc/opencv-logo.md new file mode 100644 index 0000000000..3ff85833a9 --- /dev/null +++ b/doc/opencv-logo.md @@ -0,0 +1,9 @@ +OpenCV logo has been originally designed and contributed to OpenCV by Adi Shavit in 2006. The graphical part consists of three stylized letters O, C, V, colored in the primary R, G, B color components, used by humans and computers to perceive the world. It is shaped in a way to mimic the famous [Kanizsa's triangle](https://en.wikipedia.org/wiki/Illusory_contours) to emphasize that the prior knowledge and internal processing are at least as important as the actually acquired "raw" data. + +The restyled version of the logo has been designed and contributed by [xperience.ai](https://xperience.ai/) in July 2020 for the [20th anniversary](https://opencv.org/anniversary/) of OpenCV. + +The logo uses [Exo 2](https://fonts.google.com/specimen/Exo+2#about) font by Natanael Gama distributed under OFL license. + +Higher-resolution version of the logo, as well as SVG version of it, can be obtained at OpenCV [Media Kit](https://opencv.org/resources/media-kit/). + +![](./opencv-logo2.png) \ No newline at end of file