From c8f1948d588bb21d1c6d58723ece3ced8c3fe53e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 13 Apr 2020 03:53:03 +0000 Subject: [PATCH 01/13] core: drop EXPR handing code in InputArray --- modules/core/include/opencv2/core/mat.hpp | 2 +- modules/core/src/matrix_expressions.cpp | 12 +---- modules/core/src/matrix_wrap.cpp | 57 ++++------------------- 3 files changed, 10 insertions(+), 61 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 4007031b2f..05edeac523 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -170,7 +170,7 @@ public: STD_VECTOR = 3 << KIND_SHIFT, STD_VECTOR_VECTOR = 4 << KIND_SHIFT, STD_VECTOR_MAT = 5 << KIND_SHIFT, - EXPR = 6 << KIND_SHIFT, + EXPR = 6 << KIND_SHIFT, //!< removed OPENGL_BUFFER = 7 << KIND_SHIFT, CUDA_HOST_MEM = 8 << KIND_SHIFT, CUDA_GPU_MAT = 9 << KIND_SHIFT, diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index d4f8b743cf..58c99ed19a 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -1739,13 +1739,7 @@ MatExpr Mat::mul(InputArray m, double scale) const CV_INSTRUMENT_REGION(); MatExpr e; - if(m.kind() == _InputArray::EXPR) - { - const MatExpr& me = *(const MatExpr*)m.getObj(); - me.op->multiply(MatExpr(*this), me, e, scale); - } - else - MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); + MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); return e; } @@ -1840,7 +1834,6 @@ void MatExpr::swap(MatExpr& other) _InputArray::_InputArray(const MatExpr& expr) { -#if 1 if (!isIdentity(expr)) { Mat result = expr; // TODO improve through refcount == 1 of expr.a (inplace operation is possible - except gemm?) @@ -1849,9 +1842,6 @@ _InputArray::_InputArray(const MatExpr& expr) } CV_Assert(isIdentity(expr)); init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ, &expr.a); -#else - init(FIXED_TYPE + FIXED_SIZE + EXPR + ACCESS_READ, &expr); -#endif } } // cv:: diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 4c5efd6ba5..d410ab7719 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -33,12 +33,6 @@ Mat _InputArray::getMat_(int i) const return m->getMat(accessFlags).row(i); } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return (Mat)*((const MatExpr*)obj); - } - if( k == MATX || k == STD_ARRAY ) { CV_Assert( i < 0 ); @@ -179,17 +173,6 @@ void _InputArray::getMatVector(std::vector& mv) const return; } - if( k == EXPR ) - { - Mat m = *(const MatExpr*)obj; - int n = m.size[0]; - mv.resize(n); - - for( int i = 0; i < n; i++ ) - mv[i] = m.row(i); - return; - } - if( k == MATX || k == STD_ARRAY ) { size_t n = sz.height, esz = CV_ELEM_SIZE(flags); @@ -378,7 +361,9 @@ ogl::Buffer _InputArray::getOGlBuffer() const int _InputArray::kind() const { - return flags & KIND_MASK; + int k = flags & KIND_MASK; + CV_DbgAssert(k != EXPR); + return k; } int _InputArray::rows(int i) const @@ -401,12 +386,6 @@ Size _InputArray::size(int i) const return ((const Mat*)obj)->size(); } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return ((const MatExpr*)obj)->size(); - } - if( k == UMAT ) { CV_Assert( i < 0 ); @@ -569,7 +548,7 @@ int _InputArray::sizend(int* arrsz, int i) const } else { - CV_CheckLE(dims(i), 2, "Not supported"); // TODO Support EXPR with 3+ dims + CV_CheckLE(dims(i), 2, "Not supported"); Size sz2d = size(i); d = 2; if(arrsz) @@ -626,12 +605,6 @@ int _InputArray::dims(int i) const return ((const Mat*)obj)->dims; } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return ((const MatExpr*)obj)->a.dims; - } - if( k == UMAT ) { CV_Assert( i < 0 ); @@ -772,9 +745,6 @@ int _InputArray::type(int i) const if( k == UMAT ) return ((const UMat*)obj)->type(); - if( k == EXPR ) - return ((const MatExpr*)obj)->type(); - if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return CV_MAT_TYPE(flags); @@ -861,9 +831,6 @@ bool _InputArray::empty() const if( k == UMAT ) return ((const UMat*)obj)->empty(); - if( k == EXPR ) - return false; - if( k == MATX || k == STD_ARRAY ) return false; @@ -933,7 +900,7 @@ bool _InputArray::isContinuous(int i) const if( k == UMAT ) return i < 0 ? ((const UMat*)obj)->isContinuous() : true; - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return true; @@ -974,7 +941,7 @@ bool _InputArray::isSubmatrix(int i) const if( k == UMAT ) return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false; - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return false; @@ -1019,7 +986,7 @@ size_t _InputArray::offset(int i) const return ((const UMat*)obj)->offset; } - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; @@ -1082,7 +1049,7 @@ size_t _InputArray::step(int i) const return ((const UMat*)obj)->step; } - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; @@ -1137,14 +1104,6 @@ void _InputArray::copyTo(const _OutputArray& arr) const Mat m = getMat(); m.copyTo(arr); } - else if( k == EXPR ) - { - const MatExpr& e = *((MatExpr*)obj); - if( arr.kind() == MAT ) - arr.getMatRef() = e; - else - Mat(e).copyTo(arr); - } else if( k == UMAT ) ((UMat*)obj)->copyTo(arr); #ifdef HAVE_CUDA From f84cae833adcf387a4076e343726ae242798ddc7 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 15 Apr 2020 11:18:03 +0300 Subject: [PATCH 02/13] TickMeter: added FPS and AvgTime, improved docs, reformatted --- modules/core/include/opencv2/core/utility.hpp | 109 ++++++++---------- .../tutorial_code/snippets/core_various.cpp | 28 +++++ 2 files changed, 78 insertions(+), 59 deletions(-) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index a110d34684..b97458d2d3 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -282,107 +282,98 @@ CV_EXPORTS_W double getTickFrequency(); The class computes passing time by counting the number of ticks per second. That is, the following code computes the execution time in seconds: -@code -TickMeter tm; -tm.start(); -// do something ... -tm.stop(); -std::cout << tm.getTimeSec(); -@endcode +@snippet snippets/core_various.cpp TickMeter_total It is also possible to compute the average time over multiple runs: -@code -TickMeter tm; -for (int i = 0; i < 100; i++) -{ - tm.start(); - // do something ... - tm.stop(); -} -double average_time = tm.getTimeSec() / tm.getCounter(); -std::cout << "Average time in second per iteration is: " << average_time << std::endl; -@endcode +@snippet snippets/core_various.cpp TickMeter_average + @sa getTickCount, getTickFrequency */ - class CV_EXPORTS_W TickMeter { public: //! the default constructor CV_WRAP TickMeter() { - reset(); + reset(); } - /** - starts counting ticks. - */ + //! starts counting ticks. CV_WRAP void start() { - startTime = cv::getTickCount(); + startTime = cv::getTickCount(); } - /** - stops counting ticks. - */ + //! stops counting ticks. CV_WRAP void stop() { - int64 time = cv::getTickCount(); - if (startTime == 0) - return; - ++counter; - sumTime += (time - startTime); - startTime = 0; + int64 time = cv::getTickCount(); + if (startTime == 0) + return; + ++counter; + sumTime += (time - startTime); + startTime = 0; } - /** - returns counted ticks. - */ + //! returns counted ticks. CV_WRAP int64 getTimeTicks() const { - return sumTime; + return sumTime; } - /** - returns passed time in microseconds. - */ + //! returns passed time in microseconds. CV_WRAP double getTimeMicro() const { - return getTimeMilli()*1e3; + return getTimeMilli()*1e3; } - /** - returns passed time in milliseconds. - */ + //! returns passed time in milliseconds. CV_WRAP double getTimeMilli() const { - return getTimeSec()*1e3; + return getTimeSec()*1e3; } - /** - returns passed time in seconds. - */ + //! returns passed time in seconds. CV_WRAP double getTimeSec() const { - return (double)getTimeTicks() / getTickFrequency(); + return (double)getTimeTicks() / getTickFrequency(); } - /** - returns internal counter value. - */ + //! returns internal counter value. CV_WRAP int64 getCounter() const { - return counter; + return counter; } - /** - resets internal values. - */ + //! returns average FPS (frames per second) value. + CV_WRAP double getFPS() const + { + const double sec = getTimeSec(); + if (sec < DBL_EPSILON) + return 0.; + return counter / sec; + } + + //! returns average time in seconds + CV_WRAP double getAvgTimeSec() const + { + if (counter <= 0) + return 0.; + return getTimeSec() / counter; + } + + //! returns average time in milliseconds + CV_WRAP double getAvgTimeMilli() const + { + return getAvgTimeSec() * 1e3; + } + + //! resets internal values. CV_WRAP void reset() { - startTime = 0; - sumTime = 0; - counter = 0; + startTime = 0; + sumTime = 0; + counter = 0; } private: diff --git a/samples/cpp/tutorial_code/snippets/core_various.cpp b/samples/cpp/tutorial_code/snippets/core_various.cpp index 6e220788ed..4639940856 100644 --- a/samples/cpp/tutorial_code/snippets/core_various.cpp +++ b/samples/cpp/tutorial_code/snippets/core_various.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace std; using namespace cv; @@ -52,5 +53,32 @@ int main() imshow("rectangles", test_image); waitKey(0); //! [RotatedRect_demo] + + { + //! [TickMeter_total] + TickMeter tm; + tm.start(); + // do something ... + tm.stop(); + cout << "Total time: " << tm.getTimeSec() << endl; + //! [TickMeter_total] + } + + { + const int COUNT = 100; + //! [TickMeter_average] + TickMeter tm; + for (int i = 0; i < COUNT; i++) + { + tm.start(); + // do something ... + tm.stop(); + } + cout << "Average time per iteration in seconds: " << tm.getAvgTimeSec() << endl; + cout << "Average FPS: " << tm.getFPS() << endl; + //! [TickMeter_average] + } + + return 0; } From 1cce9db710d26816563b1254f835574f40f03a8b Mon Sep 17 00:00:00 2001 From: spectralio <63775040+spectralio@users.noreply.github.com> Date: Fri, 17 Apr 2020 13:08:32 +0200 Subject: [PATCH 03/13] fix missing underscore --- modules/java/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 8cc4bd07a6..c1e1e772ce 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -19,7 +19,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/common.cmake) macro(glob_more_specific_sources _type _root _output) unset(_masks) if(${_type} STREQUAL "H") - set(_masks "${_root}/cpp/*.h" "${root}/cpp/*.hpp") + set(_masks "${_root}/cpp/*.h" "${_root}/cpp/*.hpp") elseif(${_type} STREQUAL "CPP") set(_masks "${_root}/cpp/*.cpp") elseif(${_type} STREQUAL "JAVA") From d4fc302c7ee5569be1cf540359e79c9a4b6ed3fc Mon Sep 17 00:00:00 2001 From: jshiwam <41477104+jshiwam@users.noreply.github.com> Date: Fri, 17 Apr 2020 17:46:39 +0530 Subject: [PATCH 04/13] Merge pull request #16795 from jshiwam:qrsample Added a sample file for qrcode detection in python * sample python file for qrcode detection added in samples/python * input taken using argparse and the indents were removed * Removed unused variables * updated the format and removed unused variables Removed the use of global variables and used parameterised contructor instead =set multi detection true by default * added detection from camera * samples(python): coding style in qrcode.py --- samples/python/qrcode.py | 248 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 samples/python/qrcode.py diff --git a/samples/python/qrcode.py b/samples/python/qrcode.py new file mode 100644 index 0000000000..b3253f96c6 --- /dev/null +++ b/samples/python/qrcode.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +''' +This program detects the QR-codes using OpenCV Library. + +Usage: + qrcode.py +''' + + +# Python 2/3 compatibility +from __future__ import print_function + +import numpy as np +import cv2 as cv + +import argparse +import sys + +PY3 = sys.version_info[0] == 3 +if PY3: + xrange = range + + +class QrSample: + def __init__(self, args): + self.fname = '' + self.fext = '' + self.fsaveid = 0 + self.input = args.input + self.detect = args.detect + self.out = args.out + self.multi = args.multi + self.saveDetections = args.save_detections + self.saveAll = args.save_all + + def getQRModeString(self): + msg1 = "multi " if self.multi else "" + msg2 = "detector" if self.detect else "decoder" + msg = "QR {:s}{:s}".format(msg1, msg2) + return msg + + def drawFPS(self, result, fps): + message = '{:.2f} FPS({:s})'.format(fps, self.getQRModeString()) + cv.putText(result, message, (20, 20), 1, + cv.FONT_HERSHEY_DUPLEX, (0, 0, 255)) + + def drawQRCodeContours(self, image, cnt): + if cnt.size != 0: + rows, cols, _ = image.shape + show_radius = 2.813 * ((rows / cols) if rows > cols else (cols / rows)) + contour_radius = show_radius * 0.4 + cv.drawContours(image, [cnt], 0, (0, 255, 0), int(round(contour_radius))) + tpl = cnt.reshape((-1, 2)) + for x in tuple(tpl.tolist()): + color = (255, 0, 0) + cv.circle(image, tuple(x), int(round(contour_radius)), color, -1) + + def drawQRCodeResults(self, result, points, decode_info, fps): + n = len(points) + if isinstance(decode_info, str): + decode_info = [decode_info] + if n > 0: + for i in range(n): + cnt = np.array(points[i]).reshape((-1, 1, 2)).astype(np.int32) + self.drawQRCodeContours(result, cnt) + msg = 'QR[{:d}]@{} : '.format(i, *(cnt.reshape(1, -1).tolist())) + print(msg, end="") + if len(decode_info) > i: + if decode_info[i]: + print("'", decode_info[i], "'") + else: + print("Can't decode QR code") + else: + print("Decode information is not available (disabled)") + else: + print("QRCode not detected!") + self.drawFPS(result, fps) + + def runQR(self, qrCode, inputimg): + if not self.multi: + if not self.detect: + decode_info, points, _ = qrCode.detectAndDecode(inputimg) + dec_info = decode_info + else: + _, points = qrCode.detect(inputimg) + dec_info = [] + else: + if not self.detect: + _, decode_info, points, _ = qrCode.detectAndDecodeMulti( + inputimg) + dec_info = decode_info + else: + _, points = qrCode.detectMulti(inputimg) + dec_info = [] + if points is None: + points = [] + return points, dec_info + + def DetectQRFrmImage(self, inputfile): + inputimg = cv.imread(inputfile, cv.IMREAD_COLOR) + if inputimg is None: + print('ERROR: Can not read image: {}'.format(inputfile)) + return + print('Run {:s} on image [{:d}x{:d}]'.format( + self.getQRModeString(), inputimg.shape[1], inputimg.shape[0])) + qrCode = cv.QRCodeDetector() + count = 10 + timer = cv.TickMeter() + for _ in range(count): + timer.start() + points, decode_info = self.runQR(qrCode, inputimg) + timer.stop() + fps = count / timer.getTimeSec() + print('FPS: {}'.format(fps)) + result = inputimg + self.drawQRCodeResults(result, points, decode_info, fps) + cv.imshow("QR", result) + cv.waitKey(1) + if self.out != '': + outfile = self.fname + self.fext + print("Saving Result: {}".format(outfile)) + cv.imwrite(outfile, result) + + print("Press any key to exit ...") + cv.waitKey(0) + print("Exit") + + def processQRCodeDetection(self, qrcode, frame): + if len(frame.shape) == 2: + result = cv.cvtColor(frame, cv.COLOR_GRAY2BGR) + else: + result = frame + print('Run {:s} on video frame [{:d}x{:d}]'.format( + self.getQRModeString(), frame.shape[1], frame.shape[0])) + timer = cv.TickMeter() + timer.start() + points, decode_info = self.runQR(qrcode, frame) + timer.stop() + + fps = 1 / timer.getTimeSec() + self.drawQRCodeResults(result, points, decode_info, fps) + return fps, result, points + + def DetectQRFrmCamera(self): + cap = cv.VideoCapture(0) + if not cap.isOpened(): + print("Cannot open the camera") + return + print("Press 'm' to switch between detectAndDecode and detectAndDecodeMulti") + print("Press 'd' to switch between decoder and detector") + print("Press ' ' (space) to save result into images") + print("Press 'ESC' to exit") + + qrcode = cv.QRCodeDetector() + + while True: + ret, frame = cap.read() + if not ret: + print("End of video stream") + break + forcesave = self.saveAll + result = frame + try: + fps, result, corners = self.processQRCodeDetection(qrcode, frame) + print('FPS: {:.2f}'.format(fps)) + forcesave |= self.saveDetections and (len(corners) != 0) + except cv.error as e: + print("Error exception: ", e) + forcesave = True + cv.imshow("QR code", result) + code = cv.waitKey(1) + if code < 0 and (not forcesave): + continue + if code == ord(' ') or forcesave: + fsuffix = '-{:05d}'.format(self.fsaveid) + self.fsaveid += 1 + fname_in = self.fname + fsuffix + "_input.png" + print("Saving QR code detection result: '{}' ...".format(fname_in)) + cv.imwrite(fname_in, frame) + print("Saved") + if code == ord('m'): + self.multi = not self.multi + msg = 'Switching QR code mode ==> {:s}'.format( + "detectAndDecodeMulti" if self.multi else "detectAndDecode") + print(msg) + if code == ord('d'): + self.detect = not self.detect + msg = 'Switching QR code mode ==> {:s}'.format( + "detect" if self.detect else "decode") + print(msg) + if code == 27: + print("'ESC' is pressed. Exiting...") + break + print("Exit.") + + +def main(): + parser = argparse.ArgumentParser( + description='This program detects the QR-codes input images using OpenCV Library.') + parser.add_argument( + '-i', + '--input', + help="input image path (for example, 'opencv_extra/testdata/cv/qrcode/multiple/*_qrcodes.png)", + default="", + metavar="") + parser.add_argument( + '-d', + '--detect', + help="detect QR code only (skip decoding) (default: False)", + action='store_true') + parser.add_argument( + '-m', + '--multi', + help="enable multiple qr-codes detection", + action='store_true') + parser.add_argument( + '-o', + '--out', + help="path to result file (default: qr_code.png)", + default="qr_code.png", + metavar="") + parser.add_argument( + '--save_detections', + help="save all QR detections (video mode only)", + action='store_true') + parser.add_argument( + '--save_all', + help="save all processed frames (video mode only)", + action='store_true') + args = parser.parse_args() + qrinst = QrSample(args) + if args.out != '': + index = args.out.rfind('.') + if index != -1: + qrinst.fname = args.out[:index] + qrinst.fext = args.out[index:] + else: + qrinst.fname = args.out + qrinst.fext = ".png" + if args.input != '': + qrinst.DetectQRFrmImage(args.input) + else: + qrinst.DetectQRFrmCamera() + + +if __name__ == '__main__': + main() From 28403628681d366ccb69f51e2dfe84c91860b8be Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 17 Apr 2020 17:28:42 +0300 Subject: [PATCH 05/13] Merge pull request #16769 from mshabunin:fix-ipp-install * Do not copy standalone IPP libraries to install for static builds * Restored IPP installation under option --- cmake/OpenCVFindIPP.cmake | 2 +- cmake/OpenCVFindIPPIW.cmake | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index 79555f60d9..59cd497b95 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -148,7 +148,7 @@ macro(ipp_detect_version) IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} ) list(APPEND IPP_LIBRARIES ipp${name}) - if (NOT BUILD_SHARED_LIBS) + if (NOT BUILD_SHARED_LIBS AND (HAVE_IPP_ICV OR ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;")) # CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets install(FILES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) diff --git a/cmake/OpenCVFindIPPIW.cmake b/cmake/OpenCVFindIPPIW.cmake index 5c3d8a0ea2..1e065e10f6 100644 --- a/cmake/OpenCVFindIPPIW.cmake +++ b/cmake/OpenCVFindIPPIW.cmake @@ -108,12 +108,13 @@ macro(ippiw_setup PATH BUILD) message(STATUS "found Intel IPP Integration Wrappers binaries: ${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE}") message(STATUS "at: ${IPP_IW_PATH}") - add_library(ippiw STATIC IMPORTED) - set_target_properties(ippiw PROPERTIES + add_library(ipp_iw STATIC IMPORTED) + set_target_properties(ipp_iw PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "" IMPORTED_LOCATION "${FILE}" ) - if (NOT BUILD_SHARED_LIBS) + + if (NOT BUILD_SHARED_LIBS AND ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;") # CMake doesn't support "install(TARGETS ${name} ...)" command with imported targets install(FILES "${FILE}" DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) @@ -122,7 +123,7 @@ macro(ippiw_setup PATH BUILD) endif() set(IPP_IW_INCLUDES "${IPP_IW_PATH}/include") - set(IPP_IW_LIBRARIES ippiw) + set(IPP_IW_LIBRARIES ipp_iw) set(HAVE_IPP_IW 1) set(BUILD_IPP_IW 0) From dcf7eb972edc60c6638eebd55d3e48d4cc6e0e2e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 12 Apr 2020 18:18:17 +0000 Subject: [PATCH 06/13] core(SIMD): align behavior of vector constructors - setzero() calls are dropped due low-level API nature - initialization is mandatory if necessary (not an output of other calls) --- .../include/opencv2/core/hal/intrin_avx.hpp | 28 +++++---- .../opencv2/core/hal/intrin_avx512.hpp | 57 +++++++++++++----- .../include/opencv2/core/hal/intrin_msa.hpp | 35 +++++++---- .../include/opencv2/core/hal/intrin_sse.hpp | 30 ++++++---- .../include/opencv2/core/hal/intrin_vsx.hpp | 58 ++++++++++++++----- .../include/opencv2/core/hal/intrin_wasm.hpp | 42 +++++++------- .../include/opencv2/core/hal/msa_macros.h | 0 7 files changed, 170 insertions(+), 80 deletions(-) mode change 100755 => 100644 modules/core/include/opencv2/core/hal/intrin_msa.hpp mode change 100755 => 100644 modules/core/include/opencv2/core/hal/msa_macros.h diff --git a/modules/core/include/opencv2/core/hal/intrin_avx.hpp b/modules/core/include/opencv2/core/hal/intrin_avx.hpp index ca315ae284..c977dbd5bc 100644 --- a/modules/core/include/opencv2/core/hal/intrin_avx.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_avx.hpp @@ -159,7 +159,8 @@ struct v_uint8x32 (char)v22, (char)v23, (char)v24, (char)v25, (char)v26, (char)v27, (char)v28, (char)v29, (char)v30, (char)v31); } - v_uint8x32() : val(_mm256_setzero_si256()) {} + v_uint8x32() {} + uchar get0() const { return (uchar)_v_cvtsi256_si32(val); } }; @@ -183,7 +184,8 @@ struct v_int8x32 v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31); } - v_int8x32() : val(_mm256_setzero_si256()) {} + v_int8x32() {} + schar get0() const { return (schar)_v_cvtsi256_si32(val); } }; @@ -203,7 +205,8 @@ struct v_uint16x16 (short)v4, (short)v5, (short)v6, (short)v7, (short)v8, (short)v9, (short)v10, (short)v11, (short)v12, (short)v13, (short)v14, (short)v15); } - v_uint16x16() : val(_mm256_setzero_si256()) {} + v_uint16x16() {} + ushort get0() const { return (ushort)_v_cvtsi256_si32(val); } }; @@ -222,7 +225,8 @@ struct v_int16x16 val = _mm256_setr_epi16(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_int16x16() : val(_mm256_setzero_si256()) {} + v_int16x16() {} + short get0() const { return (short)_v_cvtsi256_si32(val); } }; @@ -239,7 +243,8 @@ struct v_uint32x8 val = _mm256_setr_epi32((unsigned)v0, (unsigned)v1, (unsigned)v2, (unsigned)v3, (unsigned)v4, (unsigned)v5, (unsigned)v6, (unsigned)v7); } - v_uint32x8() : val(_mm256_setzero_si256()) {} + v_uint32x8() {} + unsigned get0() const { return (unsigned)_v_cvtsi256_si32(val); } }; @@ -255,7 +260,8 @@ struct v_int32x8 { val = _mm256_setr_epi32(v0, v1, v2, v3, v4, v5, v6, v7); } - v_int32x8() : val(_mm256_setzero_si256()) {} + v_int32x8() {} + int get0() const { return _v_cvtsi256_si32(val); } }; @@ -271,7 +277,8 @@ struct v_float32x8 { val = _mm256_setr_ps(v0, v1, v2, v3, v4, v5, v6, v7); } - v_float32x8() : val(_mm256_setzero_ps()) {} + v_float32x8() {} + float get0() const { return _mm_cvtss_f32(_mm256_castps256_ps128(val)); } }; @@ -284,7 +291,7 @@ struct v_uint64x4 explicit v_uint64x4(__m256i v) : val(v) {} v_uint64x4(uint64 v0, uint64 v1, uint64 v2, uint64 v3) { val = _mm256_setr_epi64x((int64)v0, (int64)v1, (int64)v2, (int64)v3); } - v_uint64x4() : val(_mm256_setzero_si256()) {} + v_uint64x4() {} uint64 get0() const { #if defined __x86_64__ || defined _M_X64 @@ -306,7 +313,7 @@ struct v_int64x4 explicit v_int64x4(__m256i v) : val(v) {} v_int64x4(int64 v0, int64 v1, int64 v2, int64 v3) { val = _mm256_setr_epi64x(v0, v1, v2, v3); } - v_int64x4() : val(_mm256_setzero_si256()) {} + v_int64x4() {} int64 get0() const { @@ -329,7 +336,8 @@ struct v_float64x4 explicit v_float64x4(__m256d v) : val(v) {} v_float64x4(double v0, double v1, double v2, double v3) { val = _mm256_setr_pd(v0, v1, v2, v3); } - v_float64x4() : val(_mm256_setzero_pd()) {} + v_float64x4() {} + double get0() const { return _mm_cvtsd_f64(_mm256_castpd256_pd128(val)); } }; diff --git a/modules/core/include/opencv2/core/hal/intrin_avx512.hpp b/modules/core/include/opencv2/core/hal/intrin_avx512.hpp index e189582daa..75a3bd4b85 100644 --- a/modules/core/include/opencv2/core/hal/intrin_avx512.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_avx512.hpp @@ -144,7 +144,10 @@ struct v_uint8x64 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_uint8x64() : val(_mm512_setzero_si512()) {} + v_uint8x64() {} + + static inline v_uint8x64 zero() { return v_uint8x64(_mm512_setzero_si512()); } + uchar get0() const { return (uchar)_v_cvtsi512_si32(val); } }; @@ -177,7 +180,10 @@ struct v_int8x64 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_int8x64() : val(_mm512_setzero_si512()) {} + v_int8x64() {} + + static inline v_int8x64 zero() { return v_int8x64(_mm512_setzero_si512()); } + schar get0() const { return (schar)_v_cvtsi512_si32(val); } }; @@ -200,7 +206,10 @@ struct v_uint16x32 val = _v512_set_epu16(v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_uint16x32() : val(_mm512_setzero_si512()) {} + v_uint16x32() {} + + static inline v_uint16x32 zero() { return v_uint16x32(_mm512_setzero_si512()); } + ushort get0() const { return (ushort)_v_cvtsi512_si32(val); } }; @@ -221,7 +230,10 @@ struct v_int16x32 (ushort)v15, (ushort)v14, (ushort)v13, (ushort)v12, (ushort)v11, (ushort)v10, (ushort)v9 , (ushort)v8, (ushort)v7 , (ushort)v6 , (ushort)v5 , (ushort)v4 , (ushort)v3 , (ushort)v2 , (ushort)v1 , (ushort)v0); } - v_int16x32() : val(_mm512_setzero_si512()) {} + v_int16x32() {} + + static inline v_int16x32 zero() { return v_int16x32(_mm512_setzero_si512()); } + short get0() const { return (short)_v_cvtsi512_si32(val); } }; @@ -240,7 +252,10 @@ struct v_uint32x16 val = _mm512_setr_epi32((int)v0, (int)v1, (int)v2, (int)v3, (int)v4, (int)v5, (int)v6, (int)v7, (int)v8, (int)v9, (int)v10, (int)v11, (int)v12, (int)v13, (int)v14, (int)v15); } - v_uint32x16() : val(_mm512_setzero_si512()) {} + v_uint32x16() {} + + static inline v_uint32x16 zero() { return v_uint32x16(_mm512_setzero_si512()); } + unsigned get0() const { return (unsigned)_v_cvtsi512_si32(val); } }; @@ -256,7 +271,10 @@ struct v_int32x16 { val = _mm512_setr_epi32(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_int32x16() : val(_mm512_setzero_si512()) {} + v_int32x16() {} + + static inline v_int32x16 zero() { return v_int32x16(_mm512_setzero_si512()); } + int get0() const { return _v_cvtsi512_si32(val); } }; @@ -272,7 +290,10 @@ struct v_float32x16 { val = _mm512_setr_ps(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_float32x16() : val(_mm512_setzero_ps()) {} + v_float32x16() {} + + static inline v_float32x16 zero() { return v_float32x16(_mm512_setzero_ps()); } + float get0() const { return _mm_cvtss_f32(_mm512_castps512_ps128(val)); } }; @@ -285,7 +306,10 @@ struct v_uint64x8 explicit v_uint64x8(__m512i v) : val(v) {} v_uint64x8(uint64 v0, uint64 v1, uint64 v2, uint64 v3, uint64 v4, uint64 v5, uint64 v6, uint64 v7) { val = _mm512_setr_epi64((int64)v0, (int64)v1, (int64)v2, (int64)v3, (int64)v4, (int64)v5, (int64)v6, (int64)v7); } - v_uint64x8() : val(_mm512_setzero_si512()) {} + v_uint64x8() {} + + static inline v_uint64x8 zero() { return v_uint64x8(_mm512_setzero_si512()); } + uint64 get0() const { #if defined __x86_64__ || defined _M_X64 @@ -307,7 +331,9 @@ struct v_int64x8 explicit v_int64x8(__m512i v) : val(v) {} v_int64x8(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4, int64 v5, int64 v6, int64 v7) { val = _mm512_setr_epi64(v0, v1, v2, v3, v4, v5, v6, v7); } - v_int64x8() : val(_mm512_setzero_si512()) {} + v_int64x8() {} + + static inline v_int64x8 zero() { return v_int64x8(_mm512_setzero_si512()); } int64 get0() const { @@ -330,7 +356,10 @@ struct v_float64x8 explicit v_float64x8(__m512d v) : val(v) {} v_float64x8(double v0, double v1, double v2, double v3, double v4, double v5, double v6, double v7) { val = _mm512_setr_pd(v0, v1, v2, v3, v4, v5, v6, v7); } - v_float64x8() : val(_mm512_setzero_pd()) {} + v_float64x8() {} + + static inline v_float64x8 zero() { return v_float64x8(_mm512_setzero_pd()); } + double get0() const { return _mm_cvtsd_f64(_mm512_castpd512_pd128(val)); } }; @@ -1030,7 +1059,7 @@ inline _Tpvec v_rotate_left(const _Tpvec& a, const _Tpvec& b) enum { MASK = ((1 << _Tpvec::nlanes) - 1) }; \ if (imm == 0) return a; \ if (imm == _Tpvec::nlanes) return b; \ - if (imm >= 2*_Tpvec::nlanes) return _Tpvec(); \ + if (imm >= 2*_Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_mask_expand_##suffix(_mm512_maskz_compress_##suffix((MASK << SHIFT2)&MASK, b.val), (MASK << (imm))&MASK, a.val)); \ } \ template \ @@ -1040,21 +1069,21 @@ inline _Tpvec v_rotate_right(const _Tpvec& a, const _Tpvec& b) enum { MASK = ((1 << _Tpvec::nlanes) - 1) }; \ if (imm == 0) return a; \ if (imm == _Tpvec::nlanes) return b; \ - if (imm >= 2*_Tpvec::nlanes) return _Tpvec(); \ + if (imm >= 2*_Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_mask_expand_##suffix(_mm512_maskz_compress_##suffix((MASK << (imm))&MASK, a.val), (MASK << SHIFT2)&MASK, b.val)); \ } \ template \ inline _Tpvec v_rotate_left(const _Tpvec& a) \ { \ if (imm == 0) return a; \ - if (imm >= _Tpvec::nlanes) return _Tpvec(); \ + if (imm >= _Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_maskz_expand_##suffix((1 << _Tpvec::nlanes) - (1 << (imm)), a.val)); \ } \ template \ inline _Tpvec v_rotate_right(const _Tpvec& a) \ { \ if (imm == 0) return a; \ - if (imm >= _Tpvec::nlanes) return _Tpvec(); \ + if (imm >= _Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_maskz_compress_##suffix((1 << _Tpvec::nlanes) - (1 << (imm)), a.val)); \ } diff --git a/modules/core/include/opencv2/core/hal/intrin_msa.hpp b/modules/core/include/opencv2/core/hal/intrin_msa.hpp old mode 100755 new mode 100644 index 260350c6aa..a1fbb093a8 --- a/modules/core/include/opencv2/core/hal/intrin_msa.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_msa.hpp @@ -25,7 +25,7 @@ struct v_uint8x16 typedef uchar lane_type; enum { nlanes = 16 }; - v_uint8x16() : val(msa_dupq_n_u8(0)) {} + v_uint8x16() {} explicit v_uint8x16(v16u8 v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -33,6 +33,7 @@ struct v_uint8x16 uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = msa_ld1q_u8(v); } + uchar get0() const { return msa_getq_lane_u8(val, 0); @@ -46,7 +47,7 @@ struct v_int8x16 typedef schar lane_type; enum { nlanes = 16 }; - v_int8x16() : val(msa_dupq_n_s8(0)) {} + v_int8x16() {} explicit v_int8x16(v16i8 v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -54,6 +55,7 @@ struct v_int8x16 schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = msa_ld1q_s8(v); } + schar get0() const { return msa_getq_lane_s8(val, 0); @@ -67,13 +69,14 @@ struct v_uint16x8 typedef ushort lane_type; enum { nlanes = 8 }; - v_uint16x8() : val(msa_dupq_n_u16(0)) {} + v_uint16x8() {} explicit v_uint16x8(v8u16 v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = msa_ld1q_u16(v); } + ushort get0() const { return msa_getq_lane_u16(val, 0); @@ -87,13 +90,14 @@ struct v_int16x8 typedef short lane_type; enum { nlanes = 8 }; - v_int16x8() : val(msa_dupq_n_s16(0)) {} + v_int16x8() {} explicit v_int16x8(v8i16 v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { short v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = msa_ld1q_s16(v); } + short get0() const { return msa_getq_lane_s16(val, 0); @@ -107,13 +111,14 @@ struct v_uint32x4 typedef unsigned int lane_type; enum { nlanes = 4 }; - v_uint32x4() : val(msa_dupq_n_u32(0)) {} + v_uint32x4() {} explicit v_uint32x4(v4u32 v) : val(v) {} v_uint32x4(unsigned int v0, unsigned int v1, unsigned int v2, unsigned int v3) { unsigned int v[] = {v0, v1, v2, v3}; val = msa_ld1q_u32(v); } + unsigned int get0() const { return msa_getq_lane_u32(val, 0); @@ -127,17 +132,19 @@ struct v_int32x4 typedef int lane_type; enum { nlanes = 4 }; - v_int32x4() : val(msa_dupq_n_s32(0)) {} + v_int32x4() {} explicit v_int32x4(v4i32 v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { int v[] = {v0, v1, v2, v3}; val = msa_ld1q_s32(v); } + int get0() const { return msa_getq_lane_s32(val, 0); } + v4i32 val; }; @@ -146,17 +153,19 @@ struct v_float32x4 typedef float lane_type; enum { nlanes = 4 }; - v_float32x4() : val(msa_dupq_n_f32(0.0f)) {} + v_float32x4() {} explicit v_float32x4(v4f32 v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { float v[] = {v0, v1, v2, v3}; val = msa_ld1q_f32(v); } + float get0() const { return msa_getq_lane_f32(val, 0); } + v4f32 val; }; @@ -165,17 +174,19 @@ struct v_uint64x2 typedef uint64 lane_type; enum { nlanes = 2 }; - v_uint64x2() : val(msa_dupq_n_u64(0)) {} + v_uint64x2() {} explicit v_uint64x2(v2u64 v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { uint64 v[] = {v0, v1}; val = msa_ld1q_u64(v); } + uint64 get0() const { return msa_getq_lane_u64(val, 0); } + v2u64 val; }; @@ -184,17 +195,19 @@ struct v_int64x2 typedef int64 lane_type; enum { nlanes = 2 }; - v_int64x2() : val(msa_dupq_n_s64(0)) {} + v_int64x2() {} explicit v_int64x2(v2i64 v) : val(v) {} v_int64x2(int64 v0, int64 v1) { int64 v[] = {v0, v1}; val = msa_ld1q_s64(v); } + int64 get0() const { return msa_getq_lane_s64(val, 0); } + v2i64 val; }; @@ -203,17 +216,19 @@ struct v_float64x2 typedef double lane_type; enum { nlanes = 2 }; - v_float64x2() : val(msa_dupq_n_f64(0.0f)) {} + v_float64x2() {} explicit v_float64x2(v2f64 v) : val(v) {} v_float64x2(double v0, double v1) { double v[] = {v0, v1}; val = msa_ld1q_f64(v); } + double get0() const { return msa_getq_lane_f64(val, 0); } + v2f64 val; }; diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 867ff55340..e42e4e0936 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -75,7 +75,7 @@ struct v_uint8x16 typedef __m128i vector_type; enum { nlanes = 16 }; - v_uint8x16() : val(_mm_setzero_si128()) {} + v_uint8x16() {} explicit v_uint8x16(__m128i v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -85,6 +85,7 @@ struct v_uint8x16 (char)v8, (char)v9, (char)v10, (char)v11, (char)v12, (char)v13, (char)v14, (char)v15); } + uchar get0() const { return (uchar)_mm_cvtsi128_si32(val); @@ -99,7 +100,7 @@ struct v_int8x16 typedef __m128i vector_type; enum { nlanes = 16 }; - v_int8x16() : val(_mm_setzero_si128()) {} + v_int8x16() {} explicit v_int8x16(__m128i v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -109,6 +110,7 @@ struct v_int8x16 (char)v8, (char)v9, (char)v10, (char)v11, (char)v12, (char)v13, (char)v14, (char)v15); } + schar get0() const { return (schar)_mm_cvtsi128_si32(val); @@ -123,13 +125,14 @@ struct v_uint16x8 typedef __m128i vector_type; enum { nlanes = 8 }; - v_uint16x8() : val(_mm_setzero_si128()) {} + v_uint16x8() {} explicit v_uint16x8(__m128i v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, (short)v4, (short)v5, (short)v6, (short)v7); } + ushort get0() const { return (ushort)_mm_cvtsi128_si32(val); @@ -144,13 +147,14 @@ struct v_int16x8 typedef __m128i vector_type; enum { nlanes = 8 }; - v_int16x8() : val(_mm_setzero_si128()) {} + v_int16x8() {} explicit v_int16x8(__m128i v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, (short)v4, (short)v5, (short)v6, (short)v7); } + short get0() const { return (short)_mm_cvtsi128_si32(val); @@ -165,12 +169,13 @@ struct v_uint32x4 typedef __m128i vector_type; enum { nlanes = 4 }; - v_uint32x4() : val(_mm_setzero_si128()) {} + v_uint32x4() {} explicit v_uint32x4(__m128i v) : val(v) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) { val = _mm_setr_epi32((int)v0, (int)v1, (int)v2, (int)v3); } + unsigned get0() const { return (unsigned)_mm_cvtsi128_si32(val); @@ -185,12 +190,13 @@ struct v_int32x4 typedef __m128i vector_type; enum { nlanes = 4 }; - v_int32x4() : val(_mm_setzero_si128()) {} + v_int32x4() {} explicit v_int32x4(__m128i v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { val = _mm_setr_epi32(v0, v1, v2, v3); } + int get0() const { return _mm_cvtsi128_si32(val); @@ -205,12 +211,13 @@ struct v_float32x4 typedef __m128 vector_type; enum { nlanes = 4 }; - v_float32x4() : val(_mm_setzero_ps()) {} + v_float32x4() {} explicit v_float32x4(__m128 v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { val = _mm_setr_ps(v0, v1, v2, v3); } + float get0() const { return _mm_cvtss_f32(val); @@ -225,12 +232,13 @@ struct v_uint64x2 typedef __m128i vector_type; enum { nlanes = 2 }; - v_uint64x2() : val(_mm_setzero_si128()) {} + v_uint64x2() {} explicit v_uint64x2(__m128i v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); } + uint64 get0() const { #if !defined(__x86_64__) && !defined(_M_X64) @@ -251,12 +259,13 @@ struct v_int64x2 typedef __m128i vector_type; enum { nlanes = 2 }; - v_int64x2() : val(_mm_setzero_si128()) {} + v_int64x2() {} explicit v_int64x2(__m128i v) : val(v) {} v_int64x2(int64 v0, int64 v1) { val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); } + int64 get0() const { #if !defined(__x86_64__) && !defined(_M_X64) @@ -277,12 +286,13 @@ struct v_float64x2 typedef __m128d vector_type; enum { nlanes = 2 }; - v_float64x2() : val(_mm_setzero_pd()) {} + v_float64x2() {} explicit v_float64x2(__m128d v) : val(v) {} v_float64x2(double v0, double v1) { val = _mm_setr_pd(v0, v1); } + double get0() const { return _mm_cvtsd_f64(val); diff --git a/modules/core/include/opencv2/core/hal/intrin_vsx.hpp b/modules/core/include/opencv2/core/hal/intrin_vsx.hpp index e0f6cbf635..b198643cc6 100644 --- a/modules/core/include/opencv2/core/hal/intrin_vsx.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_vsx.hpp @@ -28,7 +28,7 @@ struct v_uint8x16 explicit v_uint8x16(const vec_uchar16& v) : val(v) {} - v_uint8x16() : val(vec_uchar16_z) + v_uint8x16() {} v_uint8x16(vec_bchar16 v) : val(vec_uchar16_c(v)) {} @@ -36,6 +36,9 @@ struct v_uint8x16 uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) : val(vec_uchar16_set(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) {} + + static inline v_uint8x16 zero() { return v_uint8x16(vec_uchar16_z); } + uchar get0() const { return vec_extract(val, 0); } }; @@ -48,7 +51,7 @@ struct v_int8x16 explicit v_int8x16(const vec_char16& v) : val(v) {} - v_int8x16() : val(vec_char16_z) + v_int8x16() {} v_int8x16(vec_bchar16 v) : val(vec_char16_c(v)) {} @@ -56,6 +59,9 @@ struct v_int8x16 schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) : val(vec_char16_set(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) {} + + static inline v_int8x16 zero() { return v_int8x16(vec_char16_z); } + schar get0() const { return vec_extract(val, 0); } }; @@ -68,13 +74,16 @@ struct v_uint16x8 explicit v_uint16x8(const vec_ushort8& v) : val(v) {} - v_uint16x8() : val(vec_ushort8_z) + v_uint16x8() {} v_uint16x8(vec_bshort8 v) : val(vec_ushort8_c(v)) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) : val(vec_ushort8_set(v0, v1, v2, v3, v4, v5, v6, v7)) {} + + static inline v_uint16x8 zero() { return v_uint16x8(vec_ushort8_z); } + ushort get0() const { return vec_extract(val, 0); } }; @@ -87,13 +96,16 @@ struct v_int16x8 explicit v_int16x8(const vec_short8& v) : val(v) {} - v_int16x8() : val(vec_short8_z) + v_int16x8() {} v_int16x8(vec_bshort8 v) : val(vec_short8_c(v)) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) : val(vec_short8_set(v0, v1, v2, v3, v4, v5, v6, v7)) {} + + static inline v_int16x8 zero() { return v_int16x8(vec_short8_z); } + short get0() const { return vec_extract(val, 0); } }; @@ -106,12 +118,15 @@ struct v_uint32x4 explicit v_uint32x4(const vec_uint4& v) : val(v) {} - v_uint32x4() : val(vec_uint4_z) + v_uint32x4() {} v_uint32x4(vec_bint4 v) : val(vec_uint4_c(v)) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) : val(vec_uint4_set(v0, v1, v2, v3)) {} + + static inline v_uint32x4 zero() { return v_uint32x4(vec_uint4_z); } + uint get0() const { return vec_extract(val, 0); } }; @@ -124,12 +139,15 @@ struct v_int32x4 explicit v_int32x4(const vec_int4& v) : val(v) {} - v_int32x4() : val(vec_int4_z) + v_int32x4() {} v_int32x4(vec_bint4 v) : val(vec_int4_c(v)) {} v_int32x4(int v0, int v1, int v2, int v3) : val(vec_int4_set(v0, v1, v2, v3)) {} + + static inline v_int32x4 zero() { return v_int32x4(vec_int4_z); } + int get0() const { return vec_extract(val, 0); } }; @@ -142,12 +160,15 @@ struct v_float32x4 explicit v_float32x4(const vec_float4& v) : val(v) {} - v_float32x4() : val(vec_float4_z) + v_float32x4() {} v_float32x4(vec_bint4 v) : val(vec_float4_c(v)) {} v_float32x4(float v0, float v1, float v2, float v3) : val(vec_float4_set(v0, v1, v2, v3)) {} + + static inline v_float32x4 zero() { return v_float32x4(vec_float4_z); } + float get0() const { return vec_extract(val, 0); } }; @@ -160,12 +181,15 @@ struct v_uint64x2 explicit v_uint64x2(const vec_udword2& v) : val(v) {} - v_uint64x2() : val(vec_udword2_z) + v_uint64x2() {} v_uint64x2(vec_bdword2 v) : val(vec_udword2_c(v)) {} v_uint64x2(uint64 v0, uint64 v1) : val(vec_udword2_set(v0, v1)) {} + + static inline v_uint64x2 zero() { return v_uint64x2(vec_udword2_z); } + uint64 get0() const { return vec_extract(val, 0); } }; @@ -178,12 +202,15 @@ struct v_int64x2 explicit v_int64x2(const vec_dword2& v) : val(v) {} - v_int64x2() : val(vec_dword2_z) + v_int64x2() {} v_int64x2(vec_bdword2 v) : val(vec_dword2_c(v)) {} v_int64x2(int64 v0, int64 v1) : val(vec_dword2_set(v0, v1)) {} + + static inline v_int64x2 zero() { return v_int64x2(vec_dword2_z); } + int64 get0() const { return vec_extract(val, 0); } }; @@ -196,12 +223,15 @@ struct v_float64x2 explicit v_float64x2(const vec_double2& v) : val(v) {} - v_float64x2() : val(vec_double2_z) + v_float64x2() {} v_float64x2(vec_bdword2 v) : val(vec_double2_c(v)) {} v_float64x2(double v0, double v1) : val(vec_double2_set(v0, v1)) {} + + static inline v_float64x2 zero() { return v_float64x2(vec_double2_z); } + double get0() const { return vec_extract(val, 0); } }; @@ -229,7 +259,7 @@ OPENCV_HAL_IMPL_VSX_EXTRACT_N(v_float64x2, double) * if vec_xxx_c defined as C++ cast, clang-5 will pass it */ #define OPENCV_HAL_IMPL_VSX_INITVEC(_Tpvec, _Tp, suffix, cast) \ -inline _Tpvec v_setzero_##suffix() { return _Tpvec(); } \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec(vec_splats((_Tp)0)); } \ inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(vec_splats((_Tp)v));} \ template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0 &a) \ { return _Tpvec((cast)a.val); } @@ -660,7 +690,7 @@ inline _Tpvec v_rotate_##suffix(const _Tpvec& a) { \ const int wd = imm * sizeof(typename _Tpvec::lane_type); \ if (wd > 15) \ - return _Tpvec(); \ + return _Tpvec::zero(); \ return _Tpvec((cast)shf(vec_uchar16_c(a.val), vec_uchar16_sp(wd << 3))); \ } @@ -973,7 +1003,7 @@ inline int v_scan_forward(const v_float64x2& a) { return trailingZeros32(v_signm template inline bool v_check_all(const _Tpvec& a) -{ return vec_all_lt(a.val, _Tpvec().val); } +{ return vec_all_lt(a.val, _Tpvec::zero().val); } inline bool v_check_all(const v_uint8x16& a) { return v_check_all(v_reinterpret_as_s8(a)); } inline bool v_check_all(const v_uint16x8& a) @@ -989,7 +1019,7 @@ inline bool v_check_all(const v_float64x2& a) template inline bool v_check_any(const _Tpvec& a) -{ return vec_any_lt(a.val, _Tpvec().val); } +{ return vec_any_lt(a.val, _Tpvec::zero().val); } inline bool v_check_any(const v_uint8x16& a) { return v_check_any(v_reinterpret_as_s8(a)); } inline bool v_check_any(const v_uint16x8& a) diff --git a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp index b8c250fcc2..d1bfb6da6d 100644 --- a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp @@ -41,7 +41,7 @@ struct v_uint8x16 typedef v128_t vector_type; enum { nlanes = 16 }; - v_uint8x16() : val(wasm_i8x16_splat(0)) {} + v_uint8x16() {} explicit v_uint8x16(v128_t v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -49,6 +49,7 @@ struct v_uint8x16 uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = wasm_v128_load(v); } + uchar get0() const { return (uchar)wasm_i8x16_extract_lane(val, 0); @@ -63,7 +64,7 @@ struct v_int8x16 typedef v128_t vector_type; enum { nlanes = 16 }; - v_int8x16() : val(wasm_i8x16_splat(0)) {} + v_int8x16() {} explicit v_int8x16(v128_t v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -71,6 +72,7 @@ struct v_int8x16 schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = wasm_v128_load(v); } + schar get0() const { return wasm_i8x16_extract_lane(val, 0); @@ -85,13 +87,14 @@ struct v_uint16x8 typedef v128_t vector_type; enum { nlanes = 8 }; - v_uint16x8() : val(wasm_i16x8_splat(0)) {} + v_uint16x8() {} explicit v_uint16x8(v128_t v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = wasm_v128_load(v); } + ushort get0() const { return (ushort)wasm_i16x8_extract_lane(val, 0); // wasm_u16x8_extract_lane() unimplemented yet @@ -106,13 +109,14 @@ struct v_int16x8 typedef v128_t vector_type; enum { nlanes = 8 }; - v_int16x8() : val(wasm_i16x8_splat(0)) {} + v_int16x8() {} explicit v_int16x8(v128_t v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { short v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = wasm_v128_load(v); } + short get0() const { return wasm_i16x8_extract_lane(val, 0); @@ -127,13 +131,14 @@ struct v_uint32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_uint32x4() : val(wasm_i32x4_splat(0)) {} + v_uint32x4() {} explicit v_uint32x4(v128_t v) : val(v) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) { unsigned v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + unsigned get0() const { return (unsigned)wasm_i32x4_extract_lane(val, 0); @@ -148,13 +153,14 @@ struct v_int32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_int32x4() : val(wasm_i32x4_splat(0)) {} + v_int32x4() {} explicit v_int32x4(v128_t v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { int v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + int get0() const { return wasm_i32x4_extract_lane(val, 0); @@ -169,13 +175,14 @@ struct v_float32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_float32x4() : val(wasm_f32x4_splat(0)) {} + v_float32x4() {} explicit v_float32x4(v128_t v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { float v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + float get0() const { return wasm_f32x4_extract_lane(val, 0); @@ -190,17 +197,14 @@ struct v_uint64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_uint64x2() : val(wasm_i64x2_splat(0)) {} -#else - v_uint64x2() : val(wasm_i32x4_splat(0)) {} -#endif + v_uint64x2() {} explicit v_uint64x2(v128_t v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { uint64 v[] = {v0, v1}; val = wasm_v128_load(v); } + uint64 get0() const { #ifdef __wasm_unimplemented_simd128__ @@ -221,17 +225,14 @@ struct v_int64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_int64x2() : val(wasm_i64x2_splat(0)) {} -#else - v_int64x2() : val(wasm_i32x4_splat(0)) {} -#endif + v_int64x2() {} explicit v_int64x2(v128_t v) : val(v) {} v_int64x2(int64 v0, int64 v1) { int64 v[] = {v0, v1}; val = wasm_v128_load(v); } + int64 get0() const { #ifdef __wasm_unimplemented_simd128__ @@ -252,17 +253,14 @@ struct v_float64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_float64x2() : val(wasm_f64x2_splat(0)) {} -#else - v_float64x2() : val(wasm_f32x4_splat(0)) {} -#endif + v_float64x2() {} explicit v_float64x2(v128_t v) : val(v) {} v_float64x2(double v0, double v1) { double v[] = {v0, v1}; val = wasm_v128_load(v); } + double get0() const { #ifdef __wasm_unimplemented_simd128__ diff --git a/modules/core/include/opencv2/core/hal/msa_macros.h b/modules/core/include/opencv2/core/hal/msa_macros.h old mode 100755 new mode 100644 From 908bf935f747112a1eeb7661fc91b10a863ccf04 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sat, 18 Apr 2020 19:42:48 +0300 Subject: [PATCH 07/13] Flexible inputs for OpenVINO IR models --- modules/dnn/src/dnn.cpp | 2 ++ modules/dnn/src/ie_ngraph.cpp | 7 ++++++ modules/dnn/src/ie_ngraph.hpp | 2 ++ modules/dnn/src/op_inf_engine.cpp | 7 ++++++ modules/dnn/src/op_inf_engine.hpp | 2 ++ modules/dnn/test/test_misc.cpp | 42 +++++++++++++++++++++++++++++++ 6 files changed, 62 insertions(+) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index a7b274286f..f8a3dcab9b 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1629,6 +1629,7 @@ struct Net::Impl Ptr ieNode = node.dynamicCast(); CV_Assert(!ieNode.empty()); + ieNode->net->reset(); for (it = layers.begin(); it != layers.end(); ++it) { @@ -1930,6 +1931,7 @@ struct Net::Impl Ptr ieNode = node.dynamicCast(); CV_Assert(!ieNode.empty()); + ieNode->net->reset(); for (it = layers.begin(); it != layers.end(); ++it) { diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index e3f0966ab4..05e8205251 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -780,6 +780,13 @@ void forwardNgraph(const std::vector >& outBlobsWrappers, ieNode->net->forward(outBlobsWrappers, isAsync); } +void InfEngineNgraphNet::reset() +{ + allBlobs.clear(); + infRequests.clear(); + isInit = false; +} + void InfEngineNgraphNet::addBlobs(const std::vector >& ptrs) { auto wrappers = ngraphWrappers(ptrs); diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index 3058178cbe..efbdafa7d9 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -52,6 +52,8 @@ public: void createNet(Target targetId); void setNodePtr(std::shared_ptr* ptr); + + void reset(); private: void release(); int getNumComponents(); diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index 047292fda8..5f3af4658e 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -891,6 +891,13 @@ bool InfEngineBackendNet::isInitialized() #endif } +void InfEngineBackendNet::reset() +{ + allBlobs.clear(); + infRequests.clear(); + isInit = false; +} + void InfEngineBackendNet::addBlobs(const std::vector >& ptrs) { auto wrappers = infEngineWrappers(ptrs); diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index a2008ec4b9..a256989f96 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -112,6 +112,8 @@ public: void addBlobs(const std::vector >& ptrs); + void reset(); + private: InferenceEngine::Builder::Network netBuilder; diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 9fc9fcadbd..1ca0d39672 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -760,6 +760,48 @@ TEST_P(Test_Model_Optimizer, readFromBuffer) normAssert(ref, actual, "", 0, 0); } +TEST_P(Test_Model_Optimizer, flexible_inputs) +{ + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); + + const std::string& model = findDataFile("dnn/layers/layer_convolution_fp16.bin"); + const std::string& proto = findDataFile("dnn/layers/layer_convolution_fp16.xml"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + + Net net0 = readNet(model, proto); + net0.setPreferableTarget(targetId); + + Net net1 = readNet(model, proto); + net1.setPreferableTarget(targetId); + + // Generate inputs. + int blobSize0[] = {2, 6, 75, 113}; + Mat input0(4, &blobSize0[0], CV_32F); + randu(input0, 0, 255); + + net0.setInput(input0); + Mat ref = net0.forward().clone(); + + int blobSize1[] = {1, 6, 10, 9}; + Mat input1(4, &blobSize1[0], CV_32F); + randu(input1, 0, 255); + + net1.setInput(input1); + Mat out = net1.forward(); + EXPECT_NE(out.size, ref.size); + + net1.setInput(input0); + out = net1.forward(); + normAssert(ref, out, 0, 0); +} + INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer, dnnBackendsAndTargetsIE() ); From 041da57e87c9cdf269c576e7b0e3c8fa6834121c Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 18 Apr 2020 22:08:36 -0400 Subject: [PATCH 08/13] fix tuple error --- .../point_polygon_test/pointPolygonTest_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py b/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py index 9b5dadb94c..d01a3d30bd 100644 --- a/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py +++ b/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py @@ -46,7 +46,7 @@ for i in range(src.shape[0]): drawing[i,j,1] = 255 drawing[i,j,2] = 255 -cv.circle(drawing,maxDistPt, int(maxVal),tuple(255,255,255), 1, cv.LINE_8, 0) +cv.circle(drawing,maxDistPt, int(maxVal),(255,255,255), 1, cv.LINE_8, 0) cv.imshow('Source', src) cv.imshow('Distance and inscribed circle', drawing) cv.waitKey() From a748eba42e5d6b135749285816cff14c24affcf8 Mon Sep 17 00:00:00 2001 From: Paul Jurczak Date: Sun, 19 Apr 2020 01:14:09 -0600 Subject: [PATCH 09/13] Added descriptions of randu and randn --- modules/core/include/opencv2/core/matx.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 1b84f3afec..733f675192 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -151,7 +151,16 @@ public: static Matx ones(); static Matx eye(); static Matx diag(const diag_type& d); + /** @brief Generates uniformly distributed random numbers + @param a Range boundary. + @param b The other range boundary (boundaries don't have to be ordered, the lower boundary is inclusive, + the upper one is exclusive). + */ static Matx randu(_Tp a, _Tp b); + /** @brief Generates normally distributed random numbers + @param a Mean value. + @param b Standard deviation. + */ static Matx randn(_Tp a, _Tp b); //! dot product computed with the default precision From 8badf7f35441c02897104be40ba60ee7f4002b9d Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Tue, 21 Apr 2020 12:26:58 +0300 Subject: [PATCH 10/13] Merge pull request #17112 from l-bat:ie_region * Support nGraph Region * Support region since OpenVINO 2020.2 * Skip myriad --- modules/dnn/src/layers/region_layer.cpp | 210 +++++++++++++++++++++ modules/dnn/test/test_darknet_importer.cpp | 4 + 2 files changed, 214 insertions(+) diff --git a/modules/dnn/src/layers/region_layer.cpp b/modules/dnn/src/layers/region_layer.cpp index c33c1cb134..e2a0733652 100644 --- a/modules/dnn/src/layers/region_layer.cpp +++ b/modules/dnn/src/layers/region_layer.cpp @@ -49,6 +49,11 @@ #include "opencl_kernels_dnn.hpp" #endif +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#endif + + namespace cv { namespace dnn @@ -103,6 +108,15 @@ public: return false; } + virtual bool supportBackend(int backendId) CV_OVERRIDE + { +#ifdef HAVE_DNN_NGRAPH + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2020_2) && preferableTarget != DNN_TARGET_MYRIAD; +#endif + return backendId == DNN_BACKEND_OPENCV; + } + float logistic_activate(float x) { return 1.F / (1.F + exp(-x)); } void softmax_activate(const float* input, const int n, const float temp, float* output) @@ -344,6 +358,202 @@ public: } return flops; } + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& input = nodes[0].dynamicCast()->node; + auto parent_shape = input->get_shape(); + int64_t b = parent_shape[0]; + int64_t h = parent_shape[1]; + int64_t w = parent_shape[2]; + int64_t c = parent_shape[3]; + + int64_t cols = b * h * w * anchors; + int64_t rows = c / anchors; + auto shape_node = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{cols, rows}); + auto tr_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 0}); + + std::shared_ptr input2d; + { + input2d = std::make_shared(input, shape_node, true); + input2d = std::make_shared(input2d, tr_axes); + } + + std::shared_ptr region; + { + auto new_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{4}, std::vector{0, 3, 1, 2}); + auto tr_input = std::make_shared(input, new_axes); + + std::vector anchors_vec(blobs[0].ptr(), blobs[0].ptr() + blobs[0].total()); + std::vector mask(anchors, 1); + region = std::make_shared(tr_input, coords, classes, anchors, useSoftmax, mask, 1, 3, anchors_vec); + + auto shape_as_inp = std::make_shared(ngraph::element::i64, + ngraph::Shape{tr_input->get_shape().size()}, tr_input->get_shape().data()); + + region = std::make_shared(region, shape_as_inp, true); + new_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{4}, std::vector{0, 2, 3, 1}); + region = std::make_shared(region, new_axes); + + region = std::make_shared(region, shape_node, true); + region = std::make_shared(region, tr_axes); + } + + auto strides = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 1}); + std::vector boxes_shape{b, anchors, h, w}; + auto shape_3d = std::make_shared(ngraph::element::i64, ngraph::Shape{boxes_shape.size()}, boxes_shape.data()); + + ngraph::Shape box_broad_shape{1, (size_t)anchors, (size_t)h, (size_t)w}; + + std::shared_ptr box_x; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{0, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, cols}); + box_x = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_x = std::make_shared(box_x); + box_x = std::make_shared(box_x, shape_3d, true); + + std::vector x_indices(w * h * anchors); + auto begin = x_indices.begin(); + for (int i = 0; i < h; i++) + { + std::fill(begin + i * anchors, begin + (i + 1) * anchors, i); + } + + for (int j = 1; j < w; j++) + { + std::copy(begin, begin + h * anchors, begin + j * h * anchors); + } + auto horiz = std::make_shared(ngraph::element::f32, box_broad_shape, x_indices.data()); + box_x = std::make_shared(box_x, horiz, ngraph::op::AutoBroadcastType::NUMPY); + + auto cols_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{float(w)}); + box_x = std::make_shared(box_x, cols_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr box_y; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, cols}); + box_y = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_y = std::make_shared(box_y); + box_y = std::make_shared(box_y, shape_3d, true); + + std::vector y_indices(h * anchors); + for (int i = 0; i < h; i++) + { + std::fill(y_indices.begin() + i * anchors, y_indices.begin() + (i + 1) * anchors, i); + } + + auto vert = std::make_shared(ngraph::element::f32, ngraph::Shape{1, (size_t)anchors, (size_t)h, 1}, y_indices.data()); + box_y = std::make_shared(box_y, vert, ngraph::op::AutoBroadcastType::NUMPY); + auto rows_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{float(h)}); + box_y = std::make_shared(box_y, rows_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr box_w, box_h; + { + int hNorm, wNorm; + if (nodes.size() > 1) + { + auto node_1_shape = nodes[1].dynamicCast()->node->get_shape(); + hNorm = node_1_shape[2]; + wNorm = node_1_shape[3]; + } + else + { + hNorm = h; + wNorm = w; + } + + std::vector anchors_w(anchors), anchors_h(anchors); + for (size_t a = 0; a < anchors; ++a) + { + anchors_w[a] = blobs[0].at(0, 2 * a) / wNorm; + anchors_h[a] = blobs[0].at(0, 2 * a + 1) / hNorm; + } + + std::vector bias_w(w * h * anchors), bias_h(w * h * anchors); + for (int j = 0; j < h; j++) + { + std::copy(anchors_w.begin(), anchors_w.end(), bias_w.begin() + j * anchors); + std::copy(anchors_h.begin(), anchors_h.end(), bias_h.begin() + j * anchors); + } + + for (int i = 1; i < w; i++) + { + std::copy(bias_w.begin(), bias_w.begin() + h * anchors, bias_w.begin() + i * h * anchors); + std::copy(bias_h.begin(), bias_h.begin() + h * anchors, bias_h.begin() + i * h * anchors); + } + + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{3, cols}); + box_w = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_w = std::make_shared(box_w); + box_w = std::make_shared(box_w, shape_3d, true); + auto anchor_w_node = std::make_shared(ngraph::element::f32, box_broad_shape, bias_w.data()); + box_w = std::make_shared(box_w, anchor_w_node, ngraph::op::AutoBroadcastType::NUMPY); + + lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{3, 0}); + upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{4, cols}); + box_h = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_h = std::make_shared(box_h); + box_h = std::make_shared(box_h, shape_3d, true); + auto anchor_h_node = std::make_shared(ngraph::element::f32, box_broad_shape, bias_h.data()); + box_h = std::make_shared(box_h, anchor_h_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr scale; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{4, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{5, cols}); + scale = std::make_shared(region, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + + if (classfix == -1) + { + auto thresh_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{0.5}); + auto mask = std::make_shared(scale, thresh_node); + auto zero_node = std::make_shared(ngraph::element::f32, mask->get_shape(), std::vector(b * cols, 0)); + scale = std::make_shared(mask, scale, zero_node); + } + } + + std::shared_ptr probs; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{5, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{rows, cols}); + auto classes = std::make_shared(region, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + probs = std::make_shared(classes, scale, ngraph::op::AutoBroadcastType::NUMPY); + + auto thresh_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &thresh); + auto mask = std::make_shared(probs, thresh_node); + auto zero_node = std::make_shared(ngraph::element::f32, mask->get_shape(), std::vector((rows - 5) * cols, 0)); + probs = std::make_shared(mask, probs, zero_node); + } + + + auto concat_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, cols}); + box_x = std::make_shared(box_x, concat_shape, true); + box_y = std::make_shared(box_y, concat_shape, true); + box_w = std::make_shared(box_w, concat_shape, true); + box_h = std::make_shared(box_h, concat_shape, true); + + ngraph::NodeVector inp_nodes{box_x, box_y, box_w, box_h, scale, probs}; + std::shared_ptr result = std::make_shared(inp_nodes, 0); + result = std::make_shared(result, tr_axes); + if (b > 1) + { + std::vector sizes = {(size_t)b, result->get_shape()[0] / b, result->get_shape()[1]}; + auto shape_node = std::make_shared(ngraph::element::i64, ngraph::Shape{sizes.size()}, sizes.data()); + result = std::make_shared(result, shape_node, true); + } + + return Ptr(new InfEngineNgraphNode(result)); + } +#endif // HAVE_DNN_NGRAPH + }; Ptr RegionLayer::create(const LayerParams& params) diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 58faaa1388..6d88e3c4d4 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -530,6 +530,10 @@ TEST_P(Test_Darknet_layers, avgpool_softmax) TEST_P(Test_Darknet_layers, region) { +#if defined(INF_ENGINE_RELEASE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && INF_ENGINE_VER_MAJOR_GE(2020020000)) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); +#endif testDarknetLayer("region"); } From d37180a2c483e9fbbff4553ede54250aa67daa5c Mon Sep 17 00:00:00 2001 From: AshihsKrShrivastava Date: Fri, 10 Apr 2020 12:06:09 +0530 Subject: [PATCH 11/13] modification for upsample node fused from unfused Resize subgraph --- modules/dnn/src/onnx/onnx_importer.cpp | 30 ++++++++++++++++++------- modules/dnn/test/test_onnx_importer.cpp | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 716c9ad39c..2b0d846721 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -1397,8 +1397,7 @@ void ONNXImporter::populateNet(Net dstNet) CV_Assert(layer_id.find(node_proto.input(i)) == layer_id.end()); String interp_mode = layerParams.get("coordinate_transformation_mode"); - CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "asymmetric", - interp_mode != "tf_half_pixel_for_nn"); + CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "tf_half_pixel_for_nn"); layerParams.set("align_corners", interp_mode == "align_corners"); Mat shapes = getBlob(node_proto, constBlobs, node_proto.input_size() - 1); @@ -1426,6 +1425,22 @@ void ONNXImporter::populateNet(Net dstNet) } else if (layer_type == "Upsample") { + //fused from Resize Subgraph + if (layerParams.has("coordinate_transformation_mode")) + { + String interp_mode = layerParams.get("coordinate_transformation_mode"); + CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "tf_half_pixel_for_nn"); + + layerParams.set("align_corners", interp_mode == "align_corners"); + if (layerParams.get("mode") == "linear") + { + layerParams.set("mode", interp_mode == "pytorch_half_pixel" ? + "opencv_linear" : "bilinear"); + } + } + if (layerParams.get("mode") == "linear" && framework_name == "pytorch") + layerParams.set("mode", "opencv_linear"); + layerParams.type = "Resize"; if (layerParams.has("scales")) { @@ -1435,22 +1450,21 @@ void ONNXImporter::populateNet(Net dstNet) layerParams.set("zoom_factor_y", scales.getIntValue(2)); layerParams.set("zoom_factor_x", scales.getIntValue(3)); } - else + else if (layerParams.has("height_scale") && layerParams.has("width_scale")) { // Caffe2 layer replaceLayerParam(layerParams, "height_scale", "zoom_factor_y"); replaceLayerParam(layerParams, "width_scale", "zoom_factor_x"); } - replaceLayerParam(layerParams, "mode", "interpolation"); - - if (layerParams.get("interpolation") == "linear" && framework_name == "pytorch") { - layerParams.type = "Resize"; + else + { + // scales as input Mat scales = getBlob(node_proto, constBlobs, 1); CV_Assert(scales.total() == 4); - layerParams.set("interpolation", "opencv_linear"); layerParams.set("zoom_factor_y", scales.at(2)); layerParams.set("zoom_factor_x", scales.at(3)); } + replaceLayerParam(layerParams, "mode", "interpolation"); } else if (layer_type == "SoftMax" || layer_type == "LogSoftmax") { diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 6e47a86631..98b529b3f9 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -369,6 +369,7 @@ TEST_P(Test_ONNX_layers, ResizeUnfused) testONNXModels("upsample_unfused_opset9_torch1.4"); testONNXModels("resize_nearest_unfused_opset11_torch1.4"); testONNXModels("resize_nearest_unfused_opset11_torch1.3"); + testONNXModels("resize_bilinear_unfused_opset11_torch1.4"); } TEST_P(Test_ONNX_layers, MultyInputs) From 0be2c7018b49dbafb8f1fa719826e9a7af1e8156 Mon Sep 17 00:00:00 2001 From: Ganesh Kathiresan Date: Tue, 21 Apr 2020 16:08:58 +0530 Subject: [PATCH 12/13] Formula Fixes for 3.4 branch Foumula fix 1 Foumula fix 2 Foumula fix 3 Foumula fix 4 Foumula fix 5 Foumula fix 8 --- doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown | 2 +- modules/calib3d/include/opencv2/calib3d.hpp | 2 +- modules/imgproc/include/opencv2/imgproc.hpp | 6 +++--- modules/video/include/opencv2/video/tracking.hpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) 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 74a15597ac..7ad1266983 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -43,7 +43,7 @@ There are multiple ways in which this model can be modified so it takes into acc misclassification errors. For example, one could think of minimizing the same quantity plus a constant times the number of misclassification errors in the training data, i.e.: -\f[\min ||\beta||^{2} + C \text{(\# misclassication errors)}\f] +\f[\min ||\beta||^{2} + C \text{(misclassification errors)}\f] However, this one is not a very good solution since, among some other reasons, we do not distinguish between samples that are misclassified with a small distance to their appropriate decision region or diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index efb4618745..e5fd50e123 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -1760,7 +1760,7 @@ Optionally, it computes the essential matrix E: where \f$T_i\f$ are components of the translation vector \f$T\f$ : \f$T=[T_0, T_1, T_2]^T\f$ . And the function can also compute the fundamental matrix F: -\f[F = cameraMatrix2^{-T} E cameraMatrix1^{-1}\f] +\f[F = cameraMatrix2^{-T}\cdot E \cdot cameraMatrix1^{-1}\f] Besides the stereo-related information, the function can also perform a full calibration of each of the two cameras. However, due to the high dimensionality of the parameter space and noise in the diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 5c82dd658f..97dc794fee 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -226,7 +226,7 @@ enum MorphTypes{ enum MorphShapes { MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] MORPH_CROSS = 1, //!< a cross-shaped structuring element: - //!< \f[E_{ij} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f] + //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f] MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height) }; @@ -1457,7 +1457,7 @@ The function smooths an image using the kernel: where -\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f] +\f[\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true} \\1 & \texttt{otherwise}\end{cases}\f] Unnormalized box filter is useful for computing various integral characteristics over each pixel neighborhood, such as covariance matrices of image derivatives (used in dense optical flow @@ -1531,7 +1531,7 @@ according to the specified border mode. The function does actually compute correlation, not the convolution: -\f[\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] +\f[\texttt{dst} (x,y) = \sum _{ \substack{0\leq x' < \texttt{kernel.cols}\\{0\leq y' < \texttt{kernel.rows}}}} \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using #flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows - diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index e8566faa3a..9f344be225 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -308,7 +308,7 @@ Default values are shown in the declaration above. The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion (@cite EP08), that is -\f[\texttt{warpMatrix} = \texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f] +\f[\texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f] where From 40973bea3191df606b2ce354b9d576ed63a51e39 Mon Sep 17 00:00:00 2001 From: Polina Smolnikova <43805563+rayonnant14@users.noreply.github.com> Date: Tue, 21 Apr 2020 23:44:50 +0300 Subject: [PATCH 13/13] Merge pull request #16961 from rayonnant14:objdetect_different_return_value_issue QRDetectMulti : different return value bug fix * QRDetectMulti : bug fix * added tests * changed test image due to large size of previous test image --- .../objdetect/perf/perf_qrcode_pipeline.cpp | 2 +- modules/objdetect/src/qrcode.cpp | 20 +++++++------- modules/objdetect/test/test_qrcode.cpp | 26 +++++++++++++++---- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/modules/objdetect/perf/perf_qrcode_pipeline.cpp b/modules/objdetect/perf/perf_qrcode_pipeline.cpp index 44ab54f4b2..716eb2d779 100644 --- a/modules/objdetect/perf/perf_qrcode_pipeline.cpp +++ b/modules/objdetect/perf/perf_qrcode_pipeline.cpp @@ -114,7 +114,7 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode, INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode_Multi, ::testing::Values( "2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png", - "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" + "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" ) ); diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index aa8a9d22b2..98d4286f0d 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -1952,8 +1952,9 @@ bool QRDetectMulti::checkSets(vector >& true_points_group, vecto vector set_size(true_points_group.size()); for (size_t i = 0; i < true_points_group.size(); i++) { - set_size[i] = int(0.5 * (true_points_group[i].size() - 2 ) * (true_points_group[i].size() - 1)); + set_size[i] = int( (true_points_group[i].size() - 2 ) * (true_points_group[i].size() - 1) * true_points_group[i].size()) / 6; } + vector< vector< Vec3i > > all_points(true_points_group.size()); for (size_t i = 0; i < true_points_group.size(); i++) all_points[i].resize(set_size[i]); @@ -1961,14 +1962,15 @@ bool QRDetectMulti::checkSets(vector >& true_points_group, vecto for (size_t i = 0; i < true_points_group.size(); i++) { cur_cluster = 0; - for (size_t j = 1; j < true_points_group[i].size() - 1; j++) - for (size_t k = j + 1; k < true_points_group[i].size(); k++) - { - all_points[i][cur_cluster][0] = 0; - all_points[i][cur_cluster][1] = int(j); - all_points[i][cur_cluster][2] = int(k); - cur_cluster++; - } + for (size_t l = 0; l < true_points_group[i].size() - 2; l++) + for (size_t j = l + 1; j < true_points_group[i].size() - 1; j++) + for (size_t k = j + 1; k < true_points_group[i].size(); k++) + { + all_points[i][cur_cluster][0] = int(l); + all_points[i][cur_cluster][1] = int(j); + all_points[i][cur_cluster][2] = int(k); + cur_cluster++; + } } for (size_t i = 0; i < true_points_group.size(); i++) diff --git a/modules/objdetect/test/test_qrcode.cpp b/modules/objdetect/test/test_qrcode.cpp index 79a060db0e..a716c837ee 100644 --- a/modules/objdetect/test/test_qrcode.cpp +++ b/modules/objdetect/test/test_qrcode.cpp @@ -23,7 +23,7 @@ std::string qrcode_images_monitor[] = { }; std::string qrcode_images_multiple[] = { "2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png", - "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" + "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" }; //#define UPDATE_QRCODE_TEST_DATA #ifdef UPDATE_QRCODE_TEST_DATA @@ -138,7 +138,6 @@ TEST(Objdetect_QRCode_Monitor, generate_test_data) file_config.release(); } - TEST(Objdetect_QRCode_Multi, generate_test_data) { const std::string root = "qrcode/multiple/"; @@ -155,11 +154,12 @@ TEST(Objdetect_QRCode_Multi, generate_test_data) ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path; std::vector corners; - EXPECT_TRUE(detectQRCodeMulti(src, corners)); + QRCodeDetector qrcode; + EXPECT_TRUE(qrcode.detectMulti(src, corners)); #ifdef HAVE_QUIRC std::vector decoded_info; std::vector straight_barcode; - EXPECT_TRUE(decodeQRCodeMulti(src, corners, decoded_info, straight_barcode)); + EXPECT_TRUE(qrcode.decodeMulti(src, corners, decoded_info, straight_barcode)); #endif file_config << "x" << "[:"; for(size_t j = 0; j < corners.size(); j += 4) @@ -475,7 +475,6 @@ TEST_P(Objdetect_QRCode_Multi, regression) } } - INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_name)); INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Close, testing::ValuesIn(qrcode_images_close)); INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Monitor, testing::ValuesIn(qrcode_images_monitor)); @@ -501,6 +500,23 @@ TEST(Objdetect_QRCode_decodeMulti, decode_regression_16491) #endif } +TEST(Objdetect_QRCode_detectMulti, detect_regression_16961) +{ + const std::string name_current_image = "9_qrcodes.jpg"; + const std::string root = "qrcode/multiple/"; + + std::string image_path = findDataFile(root + name_current_image); + Mat src = imread(image_path); + ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path; + + QRCodeDetector qrcode; + std::vector corners; + EXPECT_TRUE(qrcode.detectMulti(src, corners)); + ASSERT_FALSE(corners.empty()); + size_t expect_corners_size = 36; + EXPECT_EQ(corners.size(), expect_corners_size); +} + TEST(Objdetect_QRCode_basic, not_found_qrcode) { std::vector corners;