From 6d85fa3fd2e6d579f101af756d6f6ff5b2af0b1b Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 27 Mar 2020 01:40:28 +0000 Subject: [PATCH 01/10] imgcodecs(test): rework common I/O test, added grayscale mode --- modules/imgcodecs/test/test_common.cpp | 51 +++++++++ modules/imgcodecs/test/test_common.hpp | 15 +++ modules/imgcodecs/test/test_read_write.cpp | 124 ++++++++++++++------- 3 files changed, 151 insertions(+), 39 deletions(-) create mode 100644 modules/imgcodecs/test/test_common.cpp create mode 100644 modules/imgcodecs/test/test_common.hpp diff --git a/modules/imgcodecs/test/test_common.cpp b/modules/imgcodecs/test/test_common.cpp new file mode 100644 index 0000000000..a0addafa80 --- /dev/null +++ b/modules/imgcodecs/test/test_common.cpp @@ -0,0 +1,51 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html +#include "test_precomp.hpp" +#include "test_common.hpp" + +namespace opencv_test { + +static +Mat generateTestImageBGR_() +{ + Size sz(640, 480); + Mat result(sz, CV_8UC3, Scalar::all(0)); + + const string fname = cvtest::findDataFile("../cv/shared/baboon.png"); + Mat image = imread(fname, IMREAD_COLOR); + CV_Assert(!image.empty()); + CV_CheckEQ(image.size(), Size(512, 512), ""); + Rect roi((640-512) / 2, 0, 512, 480); + image(Rect(0, 0, 512, 480)).copyTo(result(roi)); + result(Rect(0, 0, 5, 5)).setTo(Scalar(0, 0, 255)); // R + result(Rect(5, 0, 5, 5)).setTo(Scalar(0, 255, 0)); // G + result(Rect(10, 0, 5, 5)).setTo(Scalar(255, 0, 0)); // B + result(Rect(0, 5, 5, 5)).setTo(Scalar(128, 128, 128)); // gray + //imshow("test_image", result); waitKey(); + return result; +} +Mat generateTestImageBGR() +{ + static Mat image = generateTestImageBGR_(); // initialize once + CV_Assert(!image.empty()); + return image; +} + +static +Mat generateTestImageGrayscale_() +{ + Mat imageBGR = generateTestImageBGR(); + CV_Assert(!imageBGR.empty()); + + Mat result; + cvtColor(imageBGR, result, COLOR_BGR2GRAY); + return result; +} +Mat generateTestImageGrayscale() +{ + static Mat image = generateTestImageGrayscale_(); // initialize once + return image; +} + +} // namespace diff --git a/modules/imgcodecs/test/test_common.hpp b/modules/imgcodecs/test/test_common.hpp new file mode 100644 index 0000000000..ec9a5d87fa --- /dev/null +++ b/modules/imgcodecs/test/test_common.hpp @@ -0,0 +1,15 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#ifndef OPENCV_TEST_IMGCODECS_COMMON_HPP +#define OPENCV_TEST_IMGCODECS_COMMON_HPP + +namespace opencv_test { + +Mat generateTestImageBGR(); +Mat generateTestImageGrayscale(); + +} // namespace + +#endif // OPENCV_TEST_IMGCODECS_COMMON_HPP diff --git a/modules/imgcodecs/test/test_read_write.cpp b/modules/imgcodecs/test/test_read_write.cpp index 6396200ec9..c53cc5a46b 100644 --- a/modules/imgcodecs/test/test_read_write.cpp +++ b/modules/imgcodecs/test/test_read_write.cpp @@ -2,6 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html #include "test_precomp.hpp" +#include "test_common.hpp" namespace opencv_test { namespace { @@ -145,45 +146,6 @@ TEST(Imgcodecs_Image, read_write_bmp) typedef string Ext; typedef testing::TestWithParam Imgcodecs_Image; -TEST_P(Imgcodecs_Image, read_write) -{ - const string ext = this->GetParam(); - const string full_name = cv::tempfile(ext.c_str()); - const string _name = TS::ptr()->get_data_path() + "../cv/shared/baboon.png"; - const double thresDbell = 32; - - Mat image = imread(_name); - image.convertTo(image, CV_8UC3); - ASSERT_FALSE(image.empty()); - - imwrite(full_name, image); - Mat loaded = imread(full_name); - ASSERT_FALSE(loaded.empty()); - - double psnr = cvtest::PSNR(loaded, image); - EXPECT_GT(psnr, thresDbell); - - vector from_file; - FILE *f = fopen(full_name.c_str(), "rb"); - fseek(f, 0, SEEK_END); - long len = ftell(f); - from_file.resize((size_t)len); - fseek(f, 0, SEEK_SET); - from_file.resize(fread(&from_file[0], 1, from_file.size(), f)); - fclose(f); - vector buf; - imencode("." + ext, image, buf); - ASSERT_EQ(buf, from_file); - - Mat buf_loaded = imdecode(Mat(buf), 1); - ASSERT_FALSE(buf_loaded.empty()); - - psnr = cvtest::PSNR(buf_loaded, image); - EXPECT_GT(psnr, thresDbell); - - EXPECT_EQ(0, remove(full_name.c_str())); -} - const string exts[] = { #ifdef HAVE_PNG "png", @@ -209,6 +171,90 @@ const string exts[] = { #endif }; +static +void test_image_io(const Mat& image, const std::string& fname, const std::string& ext, int imreadFlag, double psnrThreshold) +{ + vector buf; + ASSERT_NO_THROW(imencode("." + ext, image, buf)); + + ASSERT_NO_THROW(imwrite(fname, image)); + + FILE *f = fopen(fname.c_str(), "rb"); + fseek(f, 0, SEEK_END); + long len = ftell(f); + cout << "File size: " << len << " bytes" << endl; + EXPECT_GT(len, 1024) << "File is small. Test or implementation is broken"; + fseek(f, 0, SEEK_SET); + vector file_buf((size_t)len); + EXPECT_EQ(len, (long)fread(&file_buf[0], 1, (size_t)len, f)); + fclose(f); f = NULL; + + EXPECT_EQ(buf, file_buf) << "imwrite() / imencode() calls must provide the same output (bit-exact)"; + + Mat buf_loaded = imdecode(Mat(buf), imreadFlag); + EXPECT_FALSE(buf_loaded.empty()); + + Mat loaded = imread(fname, imreadFlag); + EXPECT_FALSE(loaded.empty()); + + EXPECT_EQ(0, cv::norm(loaded, buf_loaded, NORM_INF)) << "imread() and imdecode() calls must provide the same result (bit-exact)"; + + double psnr = cvtest::PSNR(loaded, image); + EXPECT_GT(psnr, psnrThreshold); + + // not necessary due bitexact check above + //double buf_psnr = cvtest::PSNR(buf_loaded, image); + //EXPECT_GT(buf_psnr, psnrThreshold); + +#if 0 // debug + if (psnr <= psnrThreshold /*|| buf_psnr <= thresDbell*/) + { + cout << "File: " << fname << endl; + imshow("origin", image); + imshow("imread", loaded); + imshow("imdecode", buf_loaded); + waitKey(); + } +#endif +} + +TEST_P(Imgcodecs_Image, read_write_BGR) +{ + const string ext = this->GetParam(); + const string fname = cv::tempfile(ext.c_str()); + + double psnrThreshold = 100; + if (ext == "jpg") + psnrThreshold = 32; + + Mat image = generateTestImageBGR(); + EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_COLOR, psnrThreshold)); + + EXPECT_EQ(0, remove(fname.c_str())); +} + +TEST_P(Imgcodecs_Image, read_write_GRAYSCALE) +{ + const string ext = this->GetParam(); + + if (false + || ext == "ppm" // grayscale is not implemented + || ext == "ras" // broken (black result) + ) + throw SkipTestException("GRAYSCALE mode is not supported"); + + const string fname = cv::tempfile(ext.c_str()); + + double psnrThreshold = 100; + if (ext == "jpg") + psnrThreshold = 40; + + Mat image = generateTestImageGrayscale(); + EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_GRAYSCALE, psnrThreshold)); + + EXPECT_EQ(0, remove(fname.c_str())); +} + INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts)); TEST(Imgcodecs_Image, regression_9376) From be17f532e1e81e5dec74392b1709b1ea9af37f3c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 29 Mar 2020 02:08:27 +0000 Subject: [PATCH 02/10] imgproc(resize): fix resizeNNInvoker handling of generic pixel size --- modules/imgproc/src/resize.cpp | 7 +++---- modules/imgproc/test/test_imgwarp.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index 43458cc153..cd039fe896 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -1043,10 +1043,9 @@ public: default: for( x = 0; x < dsize.width; x++, D += pix_size ) { - const int* _tS = (const int*)(S + x_ofs[x]); - int* _tD = (int*)D; - for( int k = 0; k < pix_size4; k++ ) - _tD[k] = _tS[k]; + const uchar* _tS = S + x_ofs[x]; + for (int k = 0; k < pix_size; k++) + D[k] = _tS[k]; } } } diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index b100442127..ffd5ecca95 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1721,7 +1721,7 @@ TEST(Resize, lanczos4_regression_16192) EXPECT_EQ(cvtest::norm(dst, expected, NORM_INF), 0) << dst(Rect(0,0,8,8)); } -TEST(Resize, DISABLED_nearest_regression_15075) // reverted https://github.com/opencv/opencv/pull/16497 +TEST(Resize, nearest_regression_15075) { const int C = 5; const int i1 = 5, j1 = 5; From 61c4cfd89624617121725a119482dde278f82955 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 29 Mar 2020 02:41:50 +0000 Subject: [PATCH 03/10] imgproc(resize): drop unused 'pix_size4' --- modules/imgproc/src/resize.avx2.cpp | 28 +++++++++++++-------------- modules/imgproc/src/resize.cpp | 21 ++++++++++---------- modules/imgproc/src/resize.hpp | 8 ++++---- modules/imgproc/src/resize.sse4_1.cpp | 28 +++++++++++++-------------- 4 files changed, 42 insertions(+), 43 deletions(-) diff --git a/modules/imgproc/src/resize.avx2.cpp b/modules/imgproc/src/resize.avx2.cpp index cf568878eb..c9f53dc622 100644 --- a/modules/imgproc/src/resize.avx2.cpp +++ b/modules/imgproc/src/resize.avx2.cpp @@ -59,8 +59,8 @@ class resizeNNInvokerAVX4 CV_FINAL : public ParallelLoopBody { public: - resizeNNInvokerAVX4(const Mat& _src, Mat &_dst, int *_x_ofs, int _pix_size4, double _ify) : - ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), pix_size4(_pix_size4), + resizeNNInvokerAVX4(const Mat& _src, Mat &_dst, int *_x_ofs, double _ify) : + ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), ify(_ify) { } @@ -129,9 +129,9 @@ public: } private: - const Mat src; - Mat dst; - int* x_ofs, pix_size4; + const Mat& src; + Mat& dst; + int* x_ofs; double ify; resizeNNInvokerAVX4(const resizeNNInvokerAVX4&); @@ -142,8 +142,8 @@ class resizeNNInvokerAVX2 CV_FINAL : public ParallelLoopBody { public: - resizeNNInvokerAVX2(const Mat& _src, Mat &_dst, int *_x_ofs, int _pix_size4, double _ify) : - ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), pix_size4(_pix_size4), + resizeNNInvokerAVX2(const Mat& _src, Mat &_dst, int *_x_ofs, double _ify) : + ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), ify(_ify) { } @@ -235,24 +235,24 @@ public: } private: - const Mat src; - Mat dst; - int* x_ofs, pix_size4; + const Mat& src; + Mat& dst; + int* x_ofs; double ify; resizeNNInvokerAVX2(const resizeNNInvokerAVX2&); resizeNNInvokerAVX2& operator=(const resizeNNInvokerAVX2&); }; -void resizeNN2_AVX2(const Range& range, const Mat& src, Mat &dst, int *x_ofs, int pix_size4, double ify) +void resizeNN2_AVX2(const Range& range, const Mat& src, Mat &dst, int *x_ofs, double ify) { - resizeNNInvokerAVX2 invoker(src, dst, x_ofs, pix_size4, ify); + resizeNNInvokerAVX2 invoker(src, dst, x_ofs, ify); parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); } -void resizeNN4_AVX2(const Range& range, const Mat& src, Mat &dst, int *x_ofs, int pix_size4, double ify) +void resizeNN4_AVX2(const Range& range, const Mat& src, Mat &dst, int *x_ofs, double ify) { - resizeNNInvokerAVX4 invoker(src, dst, x_ofs, pix_size4, ify); + resizeNNInvokerAVX4 invoker(src, dst, x_ofs, ify); parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); } diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index cd039fe896..2f060b6ae0 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -970,8 +970,8 @@ class resizeNNInvoker : public ParallelLoopBody { public: - resizeNNInvoker(const Mat& _src, Mat &_dst, int *_x_ofs, int _pix_size4, double _ify) : - ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), pix_size4(_pix_size4), + resizeNNInvoker(const Mat& _src, Mat &_dst, int *_x_ofs, double _ify) : + ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), ify(_ify) { } @@ -1052,9 +1052,9 @@ public: } private: - const Mat src; - Mat dst; - int* x_ofs, pix_size4; + const Mat& src; + Mat& dst; + int* x_ofs; double ify; resizeNNInvoker(const resizeNNInvoker&); @@ -1068,7 +1068,6 @@ resizeNN( const Mat& src, Mat& dst, double fx, double fy ) AutoBuffer _x_ofs(dsize.width); int* x_ofs = _x_ofs.data(); int pix_size = (int)src.elemSize(); - int pix_size4 = (int)(pix_size / sizeof(int)); double ifx = 1./fx, ify = 1./fy; int x; @@ -1083,9 +1082,9 @@ resizeNN( const Mat& src, Mat& dst, double fx, double fy ) if(CV_CPU_HAS_SUPPORT_AVX2 && ((pix_size == 2) || (pix_size == 4))) { if(pix_size == 2) - opt_AVX2::resizeNN2_AVX2(range, src, dst, x_ofs, pix_size4, ify); + opt_AVX2::resizeNN2_AVX2(range, src, dst, x_ofs, ify); else - opt_AVX2::resizeNN4_AVX2(range, src, dst, x_ofs, pix_size4, ify); + opt_AVX2::resizeNN4_AVX2(range, src, dst, x_ofs, ify); } else #endif @@ -1093,14 +1092,14 @@ resizeNN( const Mat& src, Mat& dst, double fx, double fy ) if(CV_CPU_HAS_SUPPORT_SSE4_1 && ((pix_size == 2) || (pix_size == 4))) { if(pix_size == 2) - opt_SSE4_1::resizeNN2_SSE4_1(range, src, dst, x_ofs, pix_size4, ify); + opt_SSE4_1::resizeNN2_SSE4_1(range, src, dst, x_ofs, ify); else - opt_SSE4_1::resizeNN4_SSE4_1(range, src, dst, x_ofs, pix_size4, ify); + opt_SSE4_1::resizeNN4_SSE4_1(range, src, dst, x_ofs, ify); } else #endif { - resizeNNInvoker invoker(src, dst, x_ofs, pix_size4, ify); + resizeNNInvoker invoker(src, dst, x_ofs, ify); parallel_for_(range, invoker, dst.total()/(double)(1<<16)); } } diff --git a/modules/imgproc/src/resize.hpp b/modules/imgproc/src/resize.hpp index 53a0eb7c48..67cf5184af 100644 --- a/modules/imgproc/src/resize.hpp +++ b/modules/imgproc/src/resize.hpp @@ -56,16 +56,16 @@ namespace cv namespace opt_AVX2 { #if CV_TRY_AVX2 -void resizeNN2_AVX2(const Range&, const Mat&, Mat&, int*, int, double); -void resizeNN4_AVX2(const Range&, const Mat&, Mat&, int*, int, double); +void resizeNN2_AVX2(const Range&, const Mat&, Mat&, int*, double); +void resizeNN4_AVX2(const Range&, const Mat&, Mat&, int*, double); #endif } namespace opt_SSE4_1 { #if CV_TRY_SSE4_1 -void resizeNN2_SSE4_1(const Range&, const Mat&, Mat&, int*, int, double); -void resizeNN4_SSE4_1(const Range&, const Mat&, Mat&, int*, int, double); +void resizeNN2_SSE4_1(const Range&, const Mat&, Mat&, int*, double); +void resizeNN4_SSE4_1(const Range&, const Mat&, Mat&, int*, double); int VResizeLanczos4Vec_32f16u_SSE41(const float** src, ushort* dst, const float* beta, int width); #endif diff --git a/modules/imgproc/src/resize.sse4_1.cpp b/modules/imgproc/src/resize.sse4_1.cpp index 43f6cc67b8..311a0036f4 100644 --- a/modules/imgproc/src/resize.sse4_1.cpp +++ b/modules/imgproc/src/resize.sse4_1.cpp @@ -59,8 +59,8 @@ class resizeNNInvokerSSE2 : public ParallelLoopBody { public: - resizeNNInvokerSSE2(const Mat& _src, Mat &_dst, int *_x_ofs, int _pix_size4, double _ify) : - ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), pix_size4(_pix_size4), + resizeNNInvokerSSE2(const Mat& _src, Mat &_dst, int *_x_ofs, double _ify) : + ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), ify(_ify) { } @@ -110,9 +110,9 @@ public: } private: - const Mat src; - Mat dst; - int* x_ofs, pix_size4; + const Mat& src; + Mat& dst; + int* x_ofs; double ify; resizeNNInvokerSSE2(const resizeNNInvokerSSE2&); @@ -123,8 +123,8 @@ class resizeNNInvokerSSE4 : public ParallelLoopBody { public: - resizeNNInvokerSSE4(const Mat& _src, Mat &_dst, int *_x_ofs, int _pix_size4, double _ify) : - ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), pix_size4(_pix_size4), + resizeNNInvokerSSE4(const Mat& _src, Mat &_dst, int *_x_ofs, double _ify) : + ParallelLoopBody(), src(_src), dst(_dst), x_ofs(_x_ofs), ify(_ify) { } @@ -165,24 +165,24 @@ public: } private: - const Mat src; - Mat dst; - int* x_ofs, pix_size4; + const Mat& src; + Mat& dst; + int* x_ofs; double ify; resizeNNInvokerSSE4(const resizeNNInvokerSSE4&); resizeNNInvokerSSE4& operator=(const resizeNNInvokerSSE4&); }; -void resizeNN2_SSE4_1(const Range& range, const Mat& src, Mat &dst, int *x_ofs, int pix_size4, double ify) +void resizeNN2_SSE4_1(const Range& range, const Mat& src, Mat &dst, int *x_ofs, double ify) { - resizeNNInvokerSSE2 invoker(src, dst, x_ofs, pix_size4, ify); + resizeNNInvokerSSE2 invoker(src, dst, x_ofs, ify); parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); } -void resizeNN4_SSE4_1(const Range& range, const Mat& src, Mat &dst, int *x_ofs, int pix_size4, double ify) +void resizeNN4_SSE4_1(const Range& range, const Mat& src, Mat &dst, int *x_ofs, double ify) { - resizeNNInvokerSSE4 invoker(src, dst, x_ofs, pix_size4, ify); + resizeNNInvokerSSE4 invoker(src, dst, x_ofs, ify); parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); } From e12b1c2209f78ed454b174f593955f2d25e8c23e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 31 Mar 2020 12:19:34 +0000 Subject: [PATCH 04/10] build: updates for winpack dldt --- CMakeLists.txt | 4 +-- modules/videoio/CMakeLists.txt | 3 +- samples/_winpack_build_sample.cmd | 45 ++++++++++++++++++++------ samples/_winpack_run_python_sample.cmd | 24 ++++++++++++-- samples/python/demo.py | 22 ++++++++++--- 5 files changed, 77 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e887dc5a2..614baa2107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -971,11 +971,11 @@ endif() # for UNIX it does not make sense as LICENSE and readme will be part of the package automatically if(ANDROID OR NOT UNIX) install(FILES ${OPENCV_LICENSE_FILE} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ DESTINATION ./ COMPONENT libs) if(OPENCV_README_FILE) install(FILES ${OPENCV_README_FILE} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ DESTINATION ./ COMPONENT libs) endif() endif() diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 8c7d75a2fb..3dac3e816c 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -294,8 +294,7 @@ if(WIN32 AND HAVE_FFMPEG_WRAPPER) install(FILES "${ffmpeg_path}" DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs RENAME "${ffmpeg_bare_name_ver}") if(INSTALL_CREATE_DISTRIB) - install(FILES "${ffmpeg_dir}/opencv_ffmpeg.dll" DESTINATION "bin/" COMPONENT libs RENAME "opencv_ffmpeg${OPENCV_DLLVERSION}.dll") - install(FILES "${ffmpeg_dir}/opencv_ffmpeg_64.dll" DESTINATION "bin/" COMPONENT libs RENAME "opencv_ffmpeg${OPENCV_DLLVERSION}_64.dll") + install(FILES "${ffmpeg_dir}/opencv_ffmpeg${FFMPEG_SUFFIX}.dll" DESTINATION "bin/" COMPONENT libs RENAME "opencv_ffmpeg${OPENCV_DLLVERSION}${FFMPEG_SUFFIX}.dll") endif() endif() endmacro() diff --git a/samples/_winpack_build_sample.cmd b/samples/_winpack_build_sample.cmd index b1b4da528e..f67e192bc1 100644 --- a/samples/_winpack_build_sample.cmd +++ b/samples/_winpack_build_sample.cmd @@ -4,16 +4,24 @@ :: - > _winpack_build_sample.cmd cpp\opencv_version.cpp :: Requires: :: - CMake -:: - MSVS 2015/2017 +:: - MSVS 2015/2017/2019 :: (tools are searched on default paths or environment should be pre-configured) @echo off setlocal -set SCRIPTDIR=%~dp0 -if NOT exist "%SCRIPTDIR%\..\..\build" ( +SET SCRIPT_DIR=%~dp0 +SET "OPENCV_SETUPVARS_SCRIPT=setup_vars_opencv3.cmd" +SET "PACKAGE_BUILD_DIR=%SCRIPT_DIR%\..\..\build" +IF NOT EXIST "%PACKAGE_BUILD_DIR%\%OPENCV_SETUPVARS_SCRIPT%" ( + :: Winpack DLDT + SET "PACKAGE_BUILD_DIR=%SCRIPT_DIR%\..\..\..\build" +) +IF NOT EXIST "%PACKAGE_BUILD_DIR%\%OPENCV_SETUPVARS_SCRIPT%" ( set "MSG=OpenCV Winpack installation is required" goto die ) +:: normalize path +for %%i in ("%PACKAGE_BUILD_DIR%") do SET "PACKAGE_BUILD_DIR=%%~fi" if [%1]==[] ( set "MSG=Sample path is required" @@ -35,8 +43,8 @@ set "SRC_NAME=%~n1" echo SRC_NAME=%SRC_NAME% echo ================================================================================ -:: Path to FFMPEG binary files -set "PATH=%PATH%;%SCRIPTDIR%\..\..\build\bin\" +:: Path to root 'bin' dir +set "PATH=%PACKAGE_BUILD_DIR%\bin;%PATH%" :: Detect compiler cl /? >NUL 2>NUL nul @@ -80,7 +88,11 @@ echo SRC_FILENAME=%SRC_FILENAME% call :dirname "%SRC_FILENAME%" SRC_DIR call :dirname "%PYTHON%" PYTHON_DIR PUSHD %SRC_DIR% -CALL "%SCRIPT_DIR%\..\..\build\setup_vars_opencv3.cmd" + +CALL "%BUILD_DIR%\%OPENCV_SETUPVARS_SCRIPT%" +:: repair SCRIPT_DIR +SET "SCRIPT_DIR=%~dp0" + ECHO Run: %* %PYTHON% %* SET result=%errorlevel% @@ -94,17 +106,23 @@ IF %result% NEQ 0 ( cmd /k echo Current directory: %CD% ) ) + POPD EXIT /B %result% :rundemo PUSHD "%SCRIPT_DIR%\python" -CALL "%SCRIPT_DIR%\..\..\build\setup_vars_opencv3.cmd" + +CALL "%BUILD_DIR%\%OPENCV_SETUPVARS_SCRIPT%" +:: repair SCRIPT_DIR +SET "SCRIPT_DIR=%~dp0" + %PYTHON% demo.py SET result=%errorlevel% IF %result% NEQ 0 ( IF NOT DEFINED OPENCV_BATCH_MODE ( pause ) ) + POPD EXIT /B %result% diff --git a/samples/python/demo.py b/samples/python/demo.py index a57a5d3ea2..a56614ce4d 100755 --- a/samples/python/demo.py +++ b/samples/python/demo.py @@ -114,12 +114,24 @@ class App: def on_demo_select(self, evt): name = self.demos_lb.get( self.demos_lb.curselection()[0] ) fn = self.samples[name] - loc = {} + + descr = "" try: - execfile(fn, loc) # Python 2 - except NameError: - exec(open(fn).read(), loc) # Python 3 - descr = loc.get('__doc__', 'no-description') + if sys.version_info[0] > 2: + # Python 3.x + module_globals = {} + module_locals = {} + with open(fn, 'r') as f: + module_code = f.read() + exec(compile(module_code, fn, 'exec'), module_globals, module_locals) + descr = module_locals.get('__doc__', 'no-description') + else: + # Python 2 + module_globals = {} + execfile(fn, module_globals) # noqa: F821 + descr = module_globals.get('__doc__', 'no-description') + except Exception as e: + descr = str(e) self.linker.reset() self.text.config(state='normal') From 433c5199fd5e9de7dba13a5e94de6ac41f95e290 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 1 Apr 2020 14:40:11 +0300 Subject: [PATCH 05/10] videoio: fixed conversion in MSMF backend --- modules/videoio/src/cap_msmf.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index 90d4f6ef63..532b2bcde2 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -579,7 +579,7 @@ public: virtual bool isOpened() const CV_OVERRIDE { return isOpen; } virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_MSMF; } protected: - bool configureOutput(MediaType newType, cv::uint32_t outFormat, bool convertToFormat); + bool configureOutput(MediaType newType, cv::uint32_t outFormat); bool setTime(double time, bool rough); bool configureHW(bool enable); @@ -766,7 +766,7 @@ bool CvCapture_MSMF::configureHW(bool enable) #endif } -bool CvCapture_MSMF::configureOutput(MediaType newType, cv::uint32_t outFormat, bool convertToFormat) +bool CvCapture_MSMF::configureOutput(MediaType newType, cv::uint32_t outFormat) { FormatStorage formats; formats.read(videoFileSource.Get()); @@ -774,7 +774,7 @@ bool CvCapture_MSMF::configureOutput(MediaType newType, cv::uint32_t outFormat, dwStreamIndex = bestMatch.first.stream; nativeFormat = bestMatch.second; MediaType newFormat = nativeFormat; - if (convertToFormat) + if (convertFormat) { switch (outFormat) { @@ -834,7 +834,7 @@ bool CvCapture_MSMF::open(int index) camid = index; readCallback = cb; duration = 0; - if (configureOutput(MediaType::createDefault(), outputFormat, convertFormat)) + if (configureOutput(MediaType::createDefault(), outputFormat)) { frameStep = captureFormat.getFrameStep(); } @@ -855,7 +855,7 @@ bool CvCapture_MSMF::open(const cv::String& _filename) { isOpen = true; sampleTime = 0; - if (configureOutput(MediaType(), outputFormat, convertFormat)) + if (configureOutput(MediaType(), outputFormat)) { frameStep = captureFormat.getFrameStep(); filename = _filename; @@ -1298,42 +1298,43 @@ bool CvCapture_MSMF::setProperty( int property_id, double value ) return false; } case CV_CAP_PROP_FORMAT: - return configureOutput(newFormat, (int)cvRound(value), convertFormat); + return configureOutput(newFormat, (int)cvRound(value)); case CV_CAP_PROP_CONVERT_RGB: - return configureOutput(newFormat, outputFormat, value != 0); + convertFormat = (value != 0); + return configureOutput(newFormat, outputFormat); case CV_CAP_PROP_SAR_NUM: if (value > 0) { newFormat.aspectRatioNum = (UINT32)cvRound(value); - return configureOutput(newFormat, outputFormat, convertFormat); + return configureOutput(newFormat, outputFormat); } break; case CV_CAP_PROP_SAR_DEN: if (value > 0) { newFormat.aspectRatioDenom = (UINT32)cvRound(value); - return configureOutput(newFormat, outputFormat, convertFormat); + return configureOutput(newFormat, outputFormat); } break; case CV_CAP_PROP_FRAME_WIDTH: if (value >= 0) { newFormat.width = (UINT32)cvRound(value); - return configureOutput(newFormat, outputFormat, convertFormat); + return configureOutput(newFormat, outputFormat); } break; case CV_CAP_PROP_FRAME_HEIGHT: if (value >= 0) { newFormat.height = (UINT32)cvRound(value); - return configureOutput(newFormat, outputFormat, convertFormat); + return configureOutput(newFormat, outputFormat); } break; case CV_CAP_PROP_FPS: if (value >= 0) { newFormat.setFramerate(value); - return configureOutput(newFormat, outputFormat, convertFormat); + return configureOutput(newFormat, outputFormat); } break; case CV_CAP_PROP_FOURCC: From 09134ac881ffc4af7d66875852fd64357b5d7e42 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 1 Apr 2020 18:34:20 +0000 Subject: [PATCH 06/10] core: emit warning ONCE on ambiguous MatExpr processing --- modules/core/src/matrix_expressions.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index d7fb6e4228..57beb68e71 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -10,6 +10,7 @@ // */ #include "precomp.hpp" +#include namespace cv { @@ -1319,10 +1320,18 @@ void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const cv::add(dst, e.s, dst); } else + { + if (e.a.channels() > 1) + CV_LOG_ONCE_WARNING(NULL, "OpenCV/MatExpr: processing of multi-channel arrays might be changed in the future: " + "https://github.com/opencv/opencv/issues/16739"); cv::addWeighted(e.a, e.alpha, e.b, e.beta, e.s[0], dst); + } } else if( e.s.isReal() && (dst.data != m.data || fabs(e.alpha) != 1)) { + if (e.a.channels() > 1) + CV_LOG_ONCE_WARNING(NULL, "OpenCV/MatExpr: processing of multi-channel arrays might be changed in the future: " + "https://github.com/opencv/opencv/issues/16739"); e.a.convertTo(m, _type, e.alpha, e.s[0]); return; } From dc9ee53ff5d7de050f2abdb2056ad0fe151aa951 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 1 Apr 2020 18:45:02 +0000 Subject: [PATCH 07/10] stitching: fix range check in DpSeamFinder::computeCosts --- modules/stitching/src/seam_finders.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/stitching/src/seam_finders.cpp b/modules/stitching/src/seam_finders.cpp index 1bc0e8e8e4..c8a320dc74 100644 --- a/modules/stitching/src/seam_finders.cpp +++ b/modules/stitching/src/seam_finders.cpp @@ -745,7 +745,9 @@ void DpSeamFinder::computeCosts( { for (int x = roi.x; x < roi.br().x+1; ++x) { - if (labels_(y, x) == l && x > 0 && labels_(y, x-1) == l) + if (x > 0 && x < labels_.cols && + labels_(y, x) == l && labels_(y, x-1) == l + ) { float costColor = (diff(image1, y + dy1, x + dx1 - 1, image2, y + dy2, x + dx2) + diff(image1, y + dy1, x + dx1, image2, y + dy2, x + dx2 - 1)) / 2; @@ -769,7 +771,9 @@ void DpSeamFinder::computeCosts( { for (int x = roi.x; x < roi.br().x; ++x) { - if (labels_(y, x) == l && y > 0 && labels_(y-1, x) == l) + if (y > 0 && y < labels_.rows && + labels_(y, x) == l && labels_(y-1, x) == l + ) { float costColor = (diff(image1, y + dy1 - 1, x + dx1, image2, y + dy2, x + dx2) + diff(image1, y + dy1, x + dx1, image2, y + dy2 - 1, x + dx2)) / 2; From 585593e9fc62773c9a0158dcd742d31655a3eef9 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 2 Apr 2020 12:49:46 +0300 Subject: [PATCH 08/10] videoio: fixed MSMF writer fps handling --- modules/videoio/src/cap_msmf.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index 532b2bcde2..119873beb0 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -1566,7 +1566,7 @@ bool CvVideoWriter_MSMF::open( const cv::String& filename, int fourcc, SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitRate)) && SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) && SUCCEEDED(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight)) && - SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1)) && + SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, (UINT32)(fps * 1000), 1000)) && SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1)) && // Set the input media type. SUCCEEDED(MFCreateMediaType(&mediaTypeIn)) && @@ -1575,7 +1575,7 @@ bool CvVideoWriter_MSMF::open( const cv::String& filename, int fourcc, SUCCEEDED(mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) && SUCCEEDED(mediaTypeIn->SetUINT32(MF_MT_DEFAULT_STRIDE, 4 * videoWidth)) && //Assume BGR32 input SUCCEEDED(MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, videoWidth, videoHeight)) && - SUCCEEDED(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)fps, 1)) && + SUCCEEDED(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, (UINT32)(fps * 1000), 1000)) && SUCCEEDED(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1)) && // Set sink writer parameters SUCCEEDED(MFCreateAttributes(&spAttr, 10)) && @@ -1596,7 +1596,7 @@ bool CvVideoWriter_MSMF::open( const cv::String& filename, int fourcc, { initiated = true; rtStart = 0; - MFFrameRateToAverageTimePerFrame((UINT32)fps, 1, &rtDuration); + MFFrameRateToAverageTimePerFrame((UINT32)(fps * 1000), 1000, &rtDuration); return true; } } From 54063c40de54d3dc63e4ef6183dd25be51e56812 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 2 Apr 2020 10:10:57 +0000 Subject: [PATCH 09/10] core(ocl): options to control buffer access flags - control using of clEnqueueMapBuffer or clEnqueueReadBuffer[Rect] - added benchmarks with OpenCL buffer access use cases --- modules/core/perf/opencl/perf_matop.cpp | 135 ++++++++++++++++++++++++ modules/core/src/ocl.cpp | 21 +++- 2 files changed, 155 insertions(+), 1 deletion(-) diff --git a/modules/core/perf/opencl/perf_matop.cpp b/modules/core/perf/opencl/perf_matop.cpp index 97a881b872..5be1f431f6 100644 --- a/modules/core/perf/opencl/perf_matop.cpp +++ b/modules/core/perf/opencl/perf_matop.cpp @@ -146,6 +146,141 @@ OCL_PERF_TEST_P(CopyToFixture, CopyToWithMaskUninit, SANITY_CHECK(dst); } + + +enum ROIType { + ROI_FULL, + ROI_2_RECT, + ROI_2_TOP, // contiguous memory block + ROI_2_LEFT, + ROI_4, + ROI_16, +}; +static Rect getROI(enum ROIType t, const Size& sz) +{ + switch (t) + { + case ROI_FULL: return Rect(0, 0, sz.width, sz.height); + case ROI_2_RECT: return Rect(0, 0, sz.width * 71 / 100, sz.height * 71 / 100); // 71 = sqrt(1/2) * 100 + case ROI_2_TOP: return Rect(0, 0, sz.width, sz.height / 2); // 71 = sqrt(1/2) * 100 + case ROI_2_LEFT: return Rect(0, 0, sz.width / 2, sz.height); // 71 = sqrt(1/2) * 100 + case ROI_4: return Rect(0, 0, sz.width / 2, sz.height / 2); + case ROI_16: return Rect(0, 0, sz.width / 4, sz.height / 4); + } + CV_Assert(false); +} + +typedef TestBaseWithParam< tuple > OpenCLBuffer; + +static inline void PrintTo(const tuple& v, std::ostream* os) +{ + *os << "(" << get<0>(v) << ", " << typeToString(get<1>(v)) << ", "; + enum ROIType roiType = get<2>(v); + if (roiType == ROI_FULL) + *os << "ROI_100_FULL"; + else if (roiType == ROI_2_RECT) + *os << "ROI_050_RECT_HALF"; + else if (roiType == ROI_2_TOP) + *os << "ROI_050_TOP_HALF"; + else if (roiType == ROI_2_LEFT) + *os << "ROI_050_LEFT_HALF"; + else if (roiType == ROI_4) + *os << "ROI_025_1/4"; + else + *os << "ROI_012_1/16"; + *os << ")"; +} + +PERF_TEST_P_(OpenCLBuffer, cpu_write) +{ + const Size srcSize = get<0>(GetParam()); + const int type = get<1>(GetParam()); + const Rect roi = getROI(get<2>(GetParam()), srcSize); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type); + declare.in(src(roi), WARMUP_NONE); + + OCL_TEST_CYCLE() + { + Mat m = src(roi).getMat(ACCESS_WRITE); + m.setTo(Scalar(1, 2, 3, 4)); + } + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(OpenCLBuffer, cpu_read) +{ + const Size srcSize = get<0>(GetParam()); + const int type = get<1>(GetParam()); + const Rect roi = getROI(get<2>(GetParam()), srcSize); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type, Scalar(1, 2, 3, 4)); + declare.in(src(roi), WARMUP_NONE); + + OCL_TEST_CYCLE() + { + unsigned counter = 0; + Mat m = src(roi).getMat(ACCESS_READ); + for (int y = 0; y < m.rows; y++) + { + uchar* ptr = m.ptr(y); + size_t width_bytes = m.cols * m.elemSize(); + for (size_t x_bytes = 0; x_bytes < width_bytes; x_bytes++) + counter += (unsigned)(ptr[x_bytes]); + } + } + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(OpenCLBuffer, cpu_update) +{ + const Size srcSize = get<0>(GetParam()); + const int type = get<1>(GetParam()); + const Rect roi = getROI(get<2>(GetParam()), srcSize); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type, Scalar(1, 2, 3, 4)); + declare.in(src(roi), WARMUP_NONE); + + OCL_TEST_CYCLE() + { + Mat m = src(roi).getMat(ACCESS_READ | ACCESS_WRITE); + for (int y = 0; y < m.rows; y++) + { + uchar* ptr = m.ptr(y); + size_t width_bytes = m.cols * m.elemSize(); + for (size_t x_bytes = 0; x_bytes < width_bytes; x_bytes++) + ptr[x_bytes] += 1; + } + } + + SANITY_CHECK_NOTHING(); +} + +INSTANTIATE_TEST_CASE_P(/*FULL*/, OpenCLBuffer, + testing::Combine( + testing::Values(szVGA, sz720p, sz1080p, sz2160p), + testing::Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4), + testing::Values(ROI_FULL) + ) +); + +INSTANTIATE_TEST_CASE_P(ROI, OpenCLBuffer, + testing::Combine( + testing::Values(sz1080p, sz2160p), + testing::Values(CV_8UC1), + testing::Values(ROI_16, ROI_4, ROI_2_RECT, ROI_2_LEFT, ROI_2_TOP, ROI_FULL) + ) +); + + } } // namespace opencv_test::ocl #endif // HAVE_OPENCL diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 52533484a0..c6b6e2f0f0 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4607,6 +4607,17 @@ public: return u; } + static bool isOpenCLMapForced() // force clEnqueueMapBuffer / clEnqueueUnmapMemObject OpenCL API + { + static bool value = cv::utils::getConfigurationParameterBool("OPENCV_OPENCL_BUFFER_FORCE_MAPPING", false); + return value; + } + static bool isOpenCLCopyingForced() // force clEnqueueReadBuffer[Rect] / clEnqueueWriteBuffer[Rect] OpenCL API + { + static bool value = cv::utils::getConfigurationParameterBool("OPENCV_OPENCL_BUFFER_FORCE_COPYING", false); + return value; + } + void getBestFlags(const Context& ctx, int /*flags*/, UMatUsageFlags usageFlags, int& createFlags, int& flags0) const { const Device& dev = ctx.device(0); @@ -4614,7 +4625,15 @@ public: if ((usageFlags & USAGE_ALLOCATE_HOST_MEMORY) != 0) createFlags |= CL_MEM_ALLOC_HOST_PTR; - if( dev.hostUnifiedMemory() ) + if (!isOpenCLCopyingForced() && + (isOpenCLMapForced() || + (dev.hostUnifiedMemory() +#ifndef __APPLE__ + || dev.isIntel() +#endif + ) + ) + ) flags0 = 0; else flags0 = UMatData::COPY_ON_MAP; From 5d95a500adb9f7c067b16fc27267d2a5cf9d8b60 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 2 Apr 2020 16:51:28 +0000 Subject: [PATCH 10/10] winpack_dldt: readme update --- platforms/winpack_dldt/build_package.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platforms/winpack_dldt/build_package.py b/platforms/winpack_dldt/build_package.py index d182f9f3b7..4e0f44d9bb 100644 --- a/platforms/winpack_dldt/build_package.py +++ b/platforms/winpack_dldt/build_package.py @@ -402,7 +402,8 @@ class Builder: rm_one(os.path.join(package_opencv, item)) with open(str(self.package_dir / 'README.md'), 'w') as f: - f.write('See licensing/copying statements in "build/etc/licenses"') + f.write('See licensing/copying statements in "build/etc/licenses"\n') + f.write('Wiki page: https://github.com/opencv/opencv/wiki/Intel%27s-Deep-Learning-Inference-Engine-backend\n') log.info('Package OpenCV sources - DONE')