From f0f92cacaa3060fc237d06b058055a9ebb7a80fd Mon Sep 17 00:00:00 2001 From: Michael Platings Date: Tue, 20 Aug 2024 12:17:52 +0000 Subject: [PATCH 1/2] Avoid copying large objects This change is required by the latest version of clang-tidy. --- test/api/test_gaussian_blur.cpp | 2 +- test/api/test_separable_filter_2d.cpp | 2 +- test/api/test_sobel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index e8f1becf2..0d487b852 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -80,7 +80,7 @@ class GaussianBlurTest : public test::KernelTest { return *this; } - void test(test::Array2D mask) { + void test(const test::Array2D &mask) { test::Kernel kernel{mask}; // Use the default border values for testing. auto kSupportedBorderValues = test::default_border_values(); diff --git a/test/api/test_separable_filter_2d.cpp b/test/api/test_separable_filter_2d.cpp index df884d6dd..de2f7e19a 100644 --- a/test/api/test_separable_filter_2d.cpp +++ b/test/api/test_separable_filter_2d.cpp @@ -86,7 +86,7 @@ class SeparableFilter2DTest : public test::KernelTest { return *this; } - void test(test::Array2D mask, InputType max_value) { + void test(const test::Array2D &mask, InputType max_value) { test::Kernel kernel{mask}; // Use the default border values for testing. auto kSupportedBorderValues = test::default_border_values(); diff --git a/test/api/test_sobel.cpp b/test/api/test_sobel.cpp index 69d14be47..8f6cc71d7 100644 --- a/test/api/test_sobel.cpp +++ b/test/api/test_sobel.cpp @@ -61,7 +61,7 @@ class Sobel3x3Test : public test::KernelTest { } public: - void test(test::Array2D mask) { + void test(const test::Array2D &mask) { test::Kernel kernel{mask}; // Use the default array layouts for testing. auto array_layouts = -- GitLab From 2e118ab5783faf364dab6255041eab3c641bd982 Mon Sep 17 00:00:00 2001 From: Michael Platings Date: Tue, 20 Aug 2024 11:54:54 +0000 Subject: [PATCH 2/2] Update to OpenCV 4.10 --- .devcontainer/Dockerfile | 2 +- .gitlab-ci.yml | 2 +- .vscode/tasks.json | 4 +- SECURITY.md | 2 +- .../opencv/extra_benchmarks/opencv-4.10.patch | 661 ++++++++++++++++++ .../opencv/extra_benchmarks/opencv-4.9.patch | 10 + adapters/opencv/kleidicv_hal.cpp | 25 +- adapters/opencv/opencv-4.10.patch | 122 ++++ adapters/opencv/opencv-4.9.patch | 10 + conformity/opencv/CMakeLists.txt | 2 +- doc/build.md | 12 +- docker/Dockerfile | 2 +- scripts/benchmark/README.md | 6 +- scripts/ci-opencv.sh | 2 +- 14 files changed, 837 insertions(+), 25 deletions(-) create mode 100644 adapters/opencv/extra_benchmarks/opencv-4.10.patch create mode 100644 adapters/opencv/opencv-4.10.patch diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4a24d5797..bf3703504 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 # If changing this image ID, please also change it in .gitlab-ci.yml -FROM registry.gitlab.arm.com/kleidi/kleidicv:11 +FROM registry.gitlab.arm.com/kleidi/kleidicv:12 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51cc45f45..570f40d10 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 # If changing this image ID, please also change it in .devcontainer/Dockerfile -image: registry.gitlab.arm.com/kleidi/kleidicv:11 +image: registry.gitlab.arm.com/kleidi/kleidicv:12 # Only run CI for main branch & merge requests workflow: diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7590c4c6d..23838143f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -189,8 +189,8 @@ "options": { "env": { "CMAKE_TOOLCHAIN_FILE": "${workspaceFolder}/.devcontainer/clang_toolchain.cmake", - "OPENCV_VERSION": "4.9.0", - "OPENCV_URL": "/opt/opencv-4.9.0.tar.gz" + "OPENCV_VERSION": "4.10.0", + "OPENCV_URL": "/opt/opencv-4.10.0.tar.gz" } }, "group": { diff --git a/SECURITY.md b/SECURITY.md index f1987c52f..e27647d87 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -14,4 +14,4 @@ Scripts within this project may download and patch third party sources. These third party sources are: * Google Test 1.12.1. * Google Benchmark 1.8.3. -* OpenCV 4.9.0 (and its dependencies) +* OpenCV 4.10.0 (and its dependencies) diff --git a/adapters/opencv/extra_benchmarks/opencv-4.10.patch b/adapters/opencv/extra_benchmarks/opencv-4.10.patch new file mode 100644 index 000000000..3bc37e274 --- /dev/null +++ b/adapters/opencv/extra_benchmarks/opencv-4.10.patch @@ -0,0 +1,661 @@ +// SPDX-FileCopyrightText: 2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright (C) 2000-2022, Intel Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2015-2023, OpenCV Foundation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2008-2016, Itseez Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2023, Xperience AI, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and Robotics for Society, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2022-2023, Southern University of Science And Technology, all rights reserved. +// SPDX-FileCopyrightText: Third party copyrights are property of their respective owners. +// +// SPDX-License-Identifier: Apache-2.0 + +diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp +index 36f400e34f..2f39ff1274 100644 +--- a/modules/core/perf/perf_arithm.cpp ++++ b/modules/core/perf/perf_arithm.cpp +@@ -447,7 +447,7 @@ PERF_TEST_P_(BinaryOpTest, transposeND) + + INSTANTIATE_TEST_CASE_P(/*nothing*/ , BinaryOpTest, + testing::Combine( +- testing::Values(szVGA, sz720p, sz1080p), ++ testing::Values(szVGA, sz720p, sz1080p, sz2160p), + testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_8SC1, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, CV_32SC1, CV_32FC1) + ) + ); +diff --git a/modules/core/perf/perf_compare.cpp b/modules/core/perf/perf_compare.cpp +index be706e1a83..862b8b7c35 100644 +--- a/modules/core/perf/perf_compare.cpp ++++ b/modules/core/perf/perf_compare.cpp +@@ -11,7 +11,7 @@ typedef perf::TestBaseWithParam Size_MatType_CmpType; + + PERF_TEST_P( Size_MatType_CmpType, compare, + testing::Combine( +- testing::Values(::perf::szVGA, ::perf::sz1080p), ++ testing::Values(::perf::szVGA, ::perf::sz1080p, ::perf::sz2160p), + testing::Values(CV_8UC1, CV_8UC4, CV_8SC1, CV_16UC1, CV_16SC1, CV_32SC1, CV_32FC1), + CmpType::all() + ) +diff --git a/modules/core/perf/perf_convertTo.cpp b/modules/core/perf/perf_convertTo.cpp +index 344d81cb8a..ef5a3aa7d2 100644 +--- a/modules/core/perf/perf_convertTo.cpp ++++ b/modules/core/perf/perf_convertTo.cpp +@@ -4,17 +4,18 @@ namespace opencv_test + { + using namespace perf; + +-typedef tuple Size_DepthSrc_DepthDst_Channels_alpha_t; +-typedef perf::TestBaseWithParam Size_DepthSrc_DepthDst_Channels_alpha; ++typedef tuple Size_DepthSrc_DepthDst_Channels_alpha_beta_t; ++typedef perf::TestBaseWithParam Size_DepthSrc_DepthDst_Channels_alpha_beta; + +-PERF_TEST_P( Size_DepthSrc_DepthDst_Channels_alpha, convertTo, ++PERF_TEST_P( Size_DepthSrc_DepthDst_Channels_alpha_beta, convertTo, + testing::Combine + ( +- testing::Values(szVGA, sz1080p), ++ testing::Values(sz1080p, sz2160p), + testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), + testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), + testing::Values(1, 4), +- testing::Values(1.0, 1./255) ++ testing::Values(1.0, 1./255, 1.234), ++ testing::Values(0, 4.567) + ) + ) + { +@@ -23,6 +24,7 @@ PERF_TEST_P( Size_DepthSrc_DepthDst_Channels_alpha, convertTo, + int depthDst = get<2>(GetParam()); + int channels = get<3>(GetParam()); + double alpha = get<4>(GetParam()); ++ double beta = get<5>(GetParam()); + + int maxValue = 255; + +@@ -31,7 +33,7 @@ PERF_TEST_P( Size_DepthSrc_DepthDst_Channels_alpha, convertTo, + Mat dst(sz, CV_MAKETYPE(depthDst, channels)); + + int runs = (sz.width <= 640) ? 8 : 1; +- TEST_CYCLE_MULTIRUN(runs) src.convertTo(dst, depthDst, alpha); ++ TEST_CYCLE_MULTIRUN(runs) src.convertTo(dst, depthDst, alpha, beta); + + double eps = depthSrc <= CV_32S && (depthDst <= CV_32S || depthDst == CV_64F) ? 1e-12 : (FLT_EPSILON * maxValue); + eps = eps * std::max(1.0, fabs(alpha)); +diff --git a/modules/core/perf/perf_exp.cpp b/modules/core/perf/perf_exp.cpp +new file mode 100644 +index 0000000000..6b20e19a0c +--- /dev/null ++++ b/modules/core/perf/perf_exp.cpp +@@ -0,0 +1,59 @@ ++#include "perf_precomp.hpp" ++ ++namespace opencv_test ++{ ++using namespace perf; ++ ++typedef perf::TestBaseWithParam Exp; ++ ++PERF_TEST_P( Exp, ExpAnyInput, ++ testing::Combine ++ ( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_32FC4) ++ ) ++ ) ++{ ++ cv::RNG rng(0); ++ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ ++ Mat src(sz, type); ++ Mat dst(sz, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() cv::exp(src, dst); ++ ++ SANITY_CHECK(dst); ++} ++ ++PERF_TEST_P( Exp, ExpSmallInput, ++ testing::Combine ++ ( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_32F) ++ ) ++ ) ++{ ++ cv::RNG rng(0); ++ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ ++ Mat src(sz, type); ++ Mat dst(sz, type); ++ ++ // Keping input values in a range where output's 1st derivative is ++ // manageable (0.001 < exp'(x) < 1000) ++ rng.fill(src, cv::RNG::UNIFORM, -7.0, 7.0); ++ ++ declare.out(dst); ++ ++ TEST_CYCLE() cv::exp(src, dst); ++ ++ SANITY_CHECK(dst); ++} ++ ++} // namespace +diff --git a/modules/core/perf/perf_inRangeScalar.cpp b/modules/core/perf/perf_inRangeScalar.cpp +new file mode 100644 +index 0000000000..9ecca30b6c +--- /dev/null ++++ b/modules/core/perf/perf_inRangeScalar.cpp +@@ -0,0 +1,34 @@ ++#include "perf_precomp.hpp" ++ ++namespace opencv_test ++{ ++using namespace perf; ++ ++typedef tuple Size_TypeSrc_lb_ub_t; ++typedef perf::TestBaseWithParam Size_TypeSrc_lb_ub; ++ ++PERF_TEST_P( Size_TypeSrc_lb_ub, inRangeScalar, ++ testing::Combine ++ ( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_32FC1), ++ testing::Values(1), ++ testing::Values(2) ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ Mat lb (1, 1, type, get<2>(GetParam())); ++ Mat ub (1, 1, type, get<3>(GetParam())); ++ Mat src(size, type); ++ Mat dst(size, CV_8UC1); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() inRange( src, lb, ub, dst ); ++ ++ SANITY_CHECK(dst); ++} ++ ++} // namespace +diff --git a/modules/core/perf/perf_minMaxIdx.cpp b/modules/core/perf/perf_minMaxIdx.cpp +new file mode 100644 +index 0000000000..b5c4ddad05 +--- /dev/null ++++ b/modules/core/perf/perf_minMaxIdx.cpp +@@ -0,0 +1,34 @@ ++#include "perf_precomp.hpp" ++ ++namespace opencv_test ++{ ++using namespace perf; ++ ++PERF_TEST_P(Size_MatType, minMaxVals, testing::Combine( ++ testing::Values(TYPICAL_MAT_SIZES), ++ testing::Values(CV_8UC1, CV_8SC1, CV_16UC1, CV_16SC1, CV_32SC1, CV_32FC1) ++ ) ++ ) ++{ ++ Size sz = get<0>(GetParam()); ++ int matType = get<1>(GetParam()); ++ ++ Mat src(sz, matType); ++ double minVal, maxVal; ++ ++ if (matType == CV_8U) ++ randu(src, 1, 254 /*do not include 0 and 255 to avoid early exit on 1 byte data*/); ++ else if (matType == CV_8S) ++ randu(src, -127, 126); ++ else ++ warmup(src, WARMUP_RNG); ++ ++ declare.in(src); ++ ++ TEST_CYCLE() cv::minMaxIdx(src, &minVal, &maxVal, nullptr, nullptr); ++ ++ SANITY_CHECK(minVal, 1e-12); ++ SANITY_CHECK(maxVal, 1e-12); ++} ++ ++} // namespace +diff --git a/modules/core/perf/perf_transpose.cpp b/modules/core/perf/perf_transpose.cpp +new file mode 100644 +index 0000000000..7c6a4afaf2 +--- /dev/null ++++ b/modules/core/perf/perf_transpose.cpp +@@ -0,0 +1,50 @@ ++#include "perf_precomp.hpp" ++ ++namespace opencv_test ++{ ++using namespace perf; ++ ++typedef perf::TestBaseWithParam Transpose; ++ ++PERF_TEST_P( Transpose, Copy, ++ testing::Combine ++ ( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8U, CV_16U, CV_32S, CV_64F) ++ ) ++ ) ++{ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ ++ Mat src(sz, type); ++ Mat dst(sz, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() cv::transpose(src, dst); ++ ++ SANITY_CHECK(dst); ++} ++ ++PERF_TEST_P( Transpose, InPlace, ++ testing::Combine ++ ( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8U, CV_16U, CV_32S, CV_64F) ++ ) ++ ) ++{ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ ++ Mat src(sz, type); ++ ++ declare.in(src, WARMUP_RNG); ++ ++ TEST_CYCLE() cv::transpose(src, src); ++ ++ SANITY_CHECK(src); ++} ++ ++} // namespace +diff --git a/modules/imgproc/perf/perf_blur.cpp b/modules/imgproc/perf/perf_blur.cpp +index d1f5a6b1ca..62463e2a28 100644 +--- a/modules/imgproc/perf/perf_blur.cpp ++++ b/modules/imgproc/perf/perf_blur.cpp +@@ -35,6 +35,7 @@ PERF_TEST_P(Size_MatType_kSize, medianBlur, + + CV_ENUM(BorderType3x3, BORDER_REPLICATE, BORDER_CONSTANT) + CV_ENUM(BorderType, BORDER_REPLICATE, BORDER_CONSTANT, BORDER_REFLECT, BORDER_REFLECT101) ++CV_ENUM(BorderTypeKleidiCV, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT101, BORDER_WRAP) + + typedef tuple Size_MatType_BorderType3x3_t; + typedef perf::TestBaseWithParam Size_MatType_BorderType3x3; +@@ -45,9 +46,12 @@ typedef perf::TestBaseWithParam Size_MatType_BorderTy + typedef tuple Size_ksize_BorderType_t; + typedef perf::TestBaseWithParam Size_ksize_BorderType; + ++typedef tuple Size_MatType_BorderTypeKleidiCV_t; ++typedef perf::TestBaseWithParam Size_MatType_BorderTypeKleidiCV; ++ + PERF_TEST_P(Size_MatType_BorderType3x3, gaussianBlur3x3, + testing::Combine( +- testing::Values(szODD, szQVGA, szVGA, sz720p), ++ testing::Values(szODD, szQVGA, szVGA, sz720p, sz1080p, sz2160p), + testing::Values(CV_8UC1, CV_8UC4, CV_16UC1, CV_16SC1, CV_32FC1), + BorderType3x3::all() + ) +@@ -67,6 +71,28 @@ PERF_TEST_P(Size_MatType_BorderType3x3, gaussianBlur3x3, + SANITY_CHECK(dst, 1); + } + ++PERF_TEST_P(Size_MatType_BorderType3x3, gaussianBlur3x3_CustomSigma, ++ testing::Combine( ++ testing::Values(szODD, szQVGA, szVGA, sz720p, sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4, CV_16UC1, CV_16SC1, CV_32FC1), ++ BorderType3x3::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderType3x3 btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(3,3), 2.2, 2.2, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ + PERF_TEST_P(Size_MatType_BorderType3x3, blur3x3, + testing::Combine( + testing::Values(szODD, szQVGA, szVGA, sz720p), +@@ -188,7 +214,7 @@ PERF_TEST_P(Size_MatType_BorderType3x3, box3x3_inplace, + + PERF_TEST_P(Size_MatType_BorderType, gaussianBlur5x5, + testing::Combine( +- testing::Values(szODD, szQVGA, szVGA, sz720p), ++ testing::Values(szODD, szQVGA, szVGA, sz720p, sz1080p, sz2160p), + testing::Values(CV_8UC1, CV_8UC4, CV_16UC1, CV_16SC1, CV_32FC1), + BorderType::all() + ) +@@ -208,6 +234,116 @@ PERF_TEST_P(Size_MatType_BorderType, gaussianBlur5x5, + SANITY_CHECK(dst, 1); + } + ++PERF_TEST_P(Size_MatType_BorderType, gaussianBlur5x5_CustomSigma, ++ testing::Combine( ++ testing::Values(szODD, szQVGA, szVGA, sz720p, sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4, CV_16UC1, CV_16SC1, CV_32FC1), ++ BorderType::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderType btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(5,5), 2.2, 2.2, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ ++PERF_TEST_P(Size_MatType_BorderTypeKleidiCV, gaussianBlur7x7, ++ testing::Combine( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4), ++ BorderTypeKleidiCV::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderTypeKleidiCV btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(7,7), 0, 0, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ ++PERF_TEST_P(Size_MatType_BorderTypeKleidiCV, gaussianBlur7x7_CustomSigma, ++ testing::Combine( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4), ++ BorderTypeKleidiCV::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderTypeKleidiCV btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(7,7), 2.2, 2.2, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ ++PERF_TEST_P(Size_MatType_BorderTypeKleidiCV, gaussianBlur15x15, ++ testing::Combine( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4), ++ BorderTypeKleidiCV::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderTypeKleidiCV btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(15,15), 0, 0, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ ++PERF_TEST_P(Size_MatType_BorderTypeKleidiCV, gaussianBlur15x15_CustomSigma, ++ testing::Combine( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4), ++ BorderTypeKleidiCV::all() ++ ) ++ ) ++{ ++ Size size = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ BorderTypeKleidiCV btype = get<2>(GetParam()); ++ ++ Mat src(size, type); ++ Mat dst(size, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ TEST_CYCLE() GaussianBlur(src, dst, Size(15,15), 2.2, 2.2, btype); ++ ++ SANITY_CHECK(dst, 1); ++} ++ + PERF_TEST_P(Size_MatType_BorderType, blur5x5, + testing::Combine( + testing::Values(szVGA, sz720p), +diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp +index 5915b507ce..4a8c02df40 100644 +--- a/modules/imgproc/perf/perf_cvt_color.cpp ++++ b/modules/imgproc/perf/perf_cvt_color.cpp +@@ -319,7 +319,7 @@ typedef perf::TestBaseWithParam Size_CvtMode; + + PERF_TEST_P(Size_CvtMode, cvtColor8u, + testing::Combine( +- testing::Values(::perf::szODD, ::perf::szVGA, ::perf::sz1080p), ++ testing::Values(::perf::szODD, ::perf::szVGA, ::perf::sz1080p, ::perf::sz2160p), + CvtMode::all() + ) + ) +@@ -435,7 +435,7 @@ typedef perf::TestBaseWithParam Size_CvtMode2; + + PERF_TEST_P(Size_CvtMode2, cvtColorYUV420, + testing::Combine( +- testing::Values(szVGA, sz1080p, Size(130, 60)), ++ testing::Values(szVGA, sz1080p, sz2160p, Size(130, 60)), + CvtMode2::all() + ) + ) +diff --git a/modules/imgproc/perf/perf_morph.cpp b/modules/imgproc/perf/perf_morph.cpp +index dc9e975a21..1b73c5eaee 100644 +--- a/modules/imgproc/perf/perf_morph.cpp ++++ b/modules/imgproc/perf/perf_morph.cpp +@@ -39,4 +39,64 @@ PERF_TEST_P(Size_MatType, dilate, TYPICAL_MATS_MORPH) + SANITY_CHECK(dst); + } + ++typedef tuple MorphParams_t; ++typedef perf::TestBaseWithParam Erode; ++typedef perf::TestBaseWithParam Dilate; ++ ++PERF_TEST_P(Erode, big, ++ testing::Combine( ++ testing::Values(::perf::sz1080p, ::perf::sz2160p), ++ testing::Values(CV_8UC1), ++ testing::Values(3, 5, 17) ++ )) ++{ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ int kernelSize = get<2>(GetParam()); ++ ++ Mat src(sz, type); ++ Mat dst(sz, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ const cv::MorphShapes morph_shape = cv::MorphShapes::MORPH_RECT; ++ const cv::Size kernel{kernelSize, kernelSize}; ++ const cv::Point anchor{-1, -1}; ++ ++ cv::Mat element = cv::getStructuringElement(morph_shape, kernel, anchor); ++ ++ TEST_CYCLE() erode(src, dst, element, cv::Point(-1, -1), 1, ++ cv::BorderTypes::BORDER_CONSTANT, cv::Scalar(0xAA)); ++ ++ SANITY_CHECK(dst); ++} ++ ++PERF_TEST_P(Dilate, big, ++ testing::Combine( ++ testing::Values(::perf::sz1080p, ::perf::sz2160p), ++ testing::Values(CV_8UC1), ++ testing::Values(3, 5, 17) ++ )) ++{ ++ Size sz = get<0>(GetParam()); ++ int type = get<1>(GetParam()); ++ int kernelSize = get<2>(GetParam()); ++ ++ Mat src(sz, type); ++ Mat dst(sz, type); ++ ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ const cv::MorphShapes morph_shape = cv::MorphShapes::MORPH_RECT; ++ const cv::Size kernel{kernelSize, kernelSize}; ++ const cv::Point anchor{-1, -1}; ++ ++ cv::Mat element = cv::getStructuringElement(morph_shape, kernel, anchor); ++ ++ TEST_CYCLE() dilate(src, dst, element, cv::Point(-1, -1), 1, ++ cv::BorderTypes::BORDER_CONSTANT, cv::Scalar(0xAA)); ++ ++ SANITY_CHECK(dst); ++} ++ + } // namespace +diff --git a/modules/imgproc/perf/perf_resize.cpp b/modules/imgproc/perf/perf_resize.cpp +index 0f470a5f81..4e31ffec82 100644 +--- a/modules/imgproc/perf/perf_resize.cpp ++++ b/modules/imgproc/perf/perf_resize.cpp +@@ -67,7 +67,18 @@ PERF_TEST_P(MatInfo_SizePair, resizeUpLinearNonExact, + testing::Combine + ( + testing::Values( MATTYPE_NE_VALUES ), +- testing::Values( Size_Size_t(szVGA, szqHD), Size_Size_t(szVGA, sz720p) ) ++ testing::Values ++ ( ++ // 2*2 ++ Size_Size_t(szqHD, sz1080p), ++ Size_Size_t(sz1080p, sz2160p), ++ // 4*4 ++ Size_Size_t(cv::Size(480, 270), sz1080p), ++ Size_Size_t(szqHD, sz2160p), ++ // 8*8 ++ Size_Size_t(cv::Size(240, 135), sz1080p), ++ Size_Size_t(cv::Size(480, 270), sz2160p) ++ ) + ) + ) + { +@@ -142,7 +153,9 @@ PERF_TEST_P(MatInfo_SizePair, resizeDownLinearNonExact, + Size_Size_t(szqHD, szVGA), + Size_Size_t(sz720p, Size(120 * sz720p.width / sz720p.height, 120)), + Size_Size_t(sz720p, szVGA), +- Size_Size_t(sz720p, szQVGA) ++ Size_Size_t(sz720p, szQVGA), ++ Size_Size_t(sz1080p, szqHD), ++ Size_Size_t(sz2160p, sz1080p) + ) + ) + ) +@@ -173,7 +186,7 @@ typedef TestBaseWithParam MatInfo_Size_Scale; + PERF_TEST_P(MatInfo_Size_Scale, ResizeAreaFast, + testing::Combine( + testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16UC1, CV_16UC3, CV_16UC4), +- testing::Values(szVGA, szqHD, sz720p, sz1080p), ++ testing::Values(szVGA, szqHD, sz720p, sz1080p, sz2160p), + testing::Values(2) + ) + ) +diff --git a/modules/imgproc/perf/perf_sepfilters.cpp b/modules/imgproc/perf/perf_sepfilters.cpp +index 480aab9f20..430d5387ad 100644 +--- a/modules/imgproc/perf/perf_sepfilters.cpp ++++ b/modules/imgproc/perf/perf_sepfilters.cpp +@@ -5,7 +5,7 @@ + + namespace opencv_test { + +-#define FILTER_SRC_SIZES szODD, szQVGA, szVGA ++#define FILTER_SRC_SIZES szODD, szQVGA, szVGA, sz1080p, sz2160p + + CV_ENUM(BorderType3x3, BORDER_REPLICATE, BORDER_CONSTANT) + CV_ENUM(BorderType3x3ROI, BORDER_DEFAULT, BORDER_REPLICATE|BORDER_ISOLATED, BORDER_CONSTANT|BORDER_ISOLATED) +@@ -242,4 +242,32 @@ PERF_TEST_P(Size_MatType_dx_dy_Border3x3ROI, scharrViaSobelFilter, + SANITY_CHECK(dst); + } + ++CV_ENUM(BorderMode_KleidiCV, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101) ++typedef TestBaseWithParam> SepFilter2D_KleidiCV; ++ ++PERF_TEST_P(SepFilter2D_KleidiCV, SepFilter2D, ++ testing::Combine( ++ testing::Values(sz1080p, sz2160p), ++ testing::Values(CV_8UC1, CV_8UC4, CV_16UC1, CV_16UC4), ++ testing::Values(5), ++ BorderMode_KleidiCV::all() ++ ) ++ ) ++{ ++ const Size srcSize = get<0>(GetParam()); ++ const int type = get<1>(GetParam()), ksize = get<2>(GetParam()), borderMode = get<3>(GetParam()); ++ ++ Mat src(srcSize, type), dst(srcSize, type); ++ declare.in(src, WARMUP_RNG).out(dst); ++ ++ Mat kernelX(1, ksize, type); ++ randu(kernelX, -3.0, 3.0); ++ Mat kernelY(1, ksize, type); ++ randu(kernelY, -3.0, 3.0); ++ ++ TEST_CYCLE() cv::sepFilter2D(src, dst, -1, kernelX, kernelY, cv::Point(-1, -1), 0.0f, borderMode); ++ ++ SANITY_CHECK_NOTHING(); ++} ++ + } // namespace +diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp +index 7aa3809f27..9ff587f325 100644 +--- a/modules/ts/include/opencv2/ts/ts_perf.hpp ++++ b/modules/ts/include/opencv2/ts/ts_perf.hpp +@@ -78,7 +78,7 @@ const static cv::Size szSmall128 = cv::Size(128, 128); + #define SZ_TYPICAL ::testing::Values(::perf::szVGA, ::perf::szqHD, ::perf::sz720p, ::perf::szODD) + + +-#define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD ++#define TYPICAL_MAT_SIZES ::perf::szVGA, ::perf::sz720p, ::perf::sz1080p, ::perf::szODD, ::perf::sz2160p + #define TYPICAL_MAT_TYPES CV_8UC1, CV_8UC4, CV_32FC1 + #define TYPICAL_MATS testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( TYPICAL_MAT_TYPES ) ) + #define TYPICAL_MATS_C1 testing::Combine( testing::Values( TYPICAL_MAT_SIZES ), testing::Values( CV_8UC1, CV_32FC1 ) ) diff --git a/adapters/opencv/extra_benchmarks/opencv-4.9.patch b/adapters/opencv/extra_benchmarks/opencv-4.9.patch index 00d88a24e..f90464fe1 100644 --- a/adapters/opencv/extra_benchmarks/opencv-4.9.patch +++ b/adapters/opencv/extra_benchmarks/opencv-4.9.patch @@ -1,4 +1,14 @@ // SPDX-FileCopyrightText: 2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright (C) 2000-2022, Intel Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2015-2023, OpenCV Foundation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2008-2016, Itseez Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2023, Xperience AI, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and Robotics for Society, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2022-2023, Southern University of Science And Technology, all rights reserved. +// SPDX-FileCopyrightText: Third party copyrights are property of their respective owners. // // SPDX-License-Identifier: Apache-2.0 diff --git a/adapters/opencv/kleidicv_hal.cpp b/adapters/opencv/kleidicv_hal.cpp index 53bc16751..4a6f0c68b 100644 --- a/adapters/opencv/kleidicv_hal.cpp +++ b/adapters/opencv/kleidicv_hal.cpp @@ -903,7 +903,7 @@ kleidicv_error_t call_min_max_loc(FunctionType min_max_loc_func, double *max_value, int *min_index, int *max_index, kleidicv_thread_multithreading mt) { - size_t tmp_min_offset, tmp_max_offset; + size_t tmp_min_offset = 0, tmp_max_offset = 0; size_t *p_min_offset = (min_value || min_index) ? &tmp_min_offset : nullptr; size_t *p_max_offset = (max_value || max_index) ? &tmp_max_offset : nullptr; @@ -917,14 +917,21 @@ kleidicv_error_t call_min_max_loc(FunctionType min_max_loc_func, if (max_value) { *max_value = static_cast(src_data[tmp_max_offset]); } - if (min_index) { - /* row */ min_index[0] = tmp_min_offset / src_stride; - /* col */ min_index[1] = (tmp_min_offset % src_stride) / sizeof(T); - } - if (max_index) { - /* row */ max_index[0] = tmp_max_offset / src_stride; - /* col */ max_index[1] = (tmp_max_offset % src_stride) / sizeof(T); - } + + // Convert from offset into array to x,y coordinates. + auto offset_to_coords = [](int *coords, size_t offset, size_t src_stride) { + if (!coords) return; + if (src_stride) { + /* row */ coords[0] = offset / src_stride; + /* col */ coords[1] = (offset % src_stride) / sizeof(T); + } else { + /* row */ coords[0] = 0; + /* col */ coords[1] = offset / sizeof(T); + } + }; + offset_to_coords(min_index, tmp_min_offset, src_stride); + offset_to_coords(max_index, tmp_max_offset, src_stride); + return err; } diff --git a/adapters/opencv/opencv-4.10.patch b/adapters/opencv/opencv-4.10.patch new file mode 100644 index 000000000..f3a8e6d0e --- /dev/null +++ b/adapters/opencv/opencv-4.10.patch @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright (C) 2000-2022, Intel Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2015-2023, OpenCV Foundation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2008-2016, Itseez Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2023, Xperience AI, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and Robotics for Society, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2022-2023, Southern University of Science And Technology, all rights reserved. +// SPDX-FileCopyrightText: Third party copyrights are property of their respective owners. +// +// SPDX-License-Identifier: Apache-2.0 + +diff --git a/modules/core/src/convert.dispatch.cpp b/modules/core/src/convert.dispatch.cpp +index 2b4035285f..729cd1dd43 100644 +--- a/modules/core/src/convert.dispatch.cpp ++++ b/modules/core/src/convert.dispatch.cpp +@@ -281,6 +281,11 @@ void Mat::convertTo(OutputArray dst, int type_, double alpha, double beta) const + dst.create(dims, size, dtype); + Mat dstMat = dst.getMat(); + ++ if( dims <= 2 ) { ++ int width_in_elements = src.cols * cn; ++ CALL_HAL(convertTo, cv_hal_convertTo, src.data, src.step, src.depth(), dstMat.data, dstMat.step, dstMat.depth(), width_in_elements, src.rows, alpha, beta); ++ } ++ + BinaryFunc func = noScale ? getConvertFunc(sdepth, ddepth) : getConvertScaleFunc(sdepth, ddepth); + double scale[] = {alpha, beta}; + CV_Assert( func != 0 ); +diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp +index f78608dbad..299b5e54bd 100644 +--- a/modules/core/src/hal_replacement.hpp ++++ b/modules/core/src/hal_replacement.hpp +@@ -953,6 +953,41 @@ inline int hal_ni_transpose2d(const uchar* src_data, size_t src_step, uchar* dst + #define cv_hal_transpose2d hal_ni_transpose2d + //! @endcond + ++/** ++ @brief convertTo ++ @param src_data,src_step,src_depth Source image ++ @param dst_data,dst_step,dst_depth Destination image ++ @param width,height Source image dimensions ++ @param scale,shift Dst values = src_value * scale + shift ++*/ ++inline int hal_ni_convertTo(const uchar *src_data, size_t src_step, int src_depth, ++ uchar *dst_data, size_t dst_step, int dst_depth, int width, ++ int height, double scale, double shift) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } ++ ++//! @cond IGNORED ++#define cv_hal_convertTo hal_ni_convertTo ++//! @endcond ++ ++/** ++ @brief inRange ++ @param src_data,src_step,src_depth Source image ++ @param dst_data,dst_step,dst_depth Destination image ++ @param width,height Source image dimensions ++ @param cn number of channels ++ @param lower_bound,upper_bound Dst values = (lower_bound <= src_value) && (src_value <= upper_bound) ? 255 : 0 ++*/ ++inline int hal_ni_inRange8u(const uchar *src_data, size_t src_step, ++ uchar *dst_data, size_t dst_step, int dst_depth, int width, ++ int height, int cn, uchar lower_bound, uchar upper_bound) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } ++inline int hal_ni_inRange32f(const uchar *src_data, size_t src_step, ++ uchar *dst_data, size_t dst_step, int dst_depth, int width, ++ int height, int cn, double lower_bound, double upper_bound) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } ++ ++//! @cond IGNORED ++#define cv_hal_inRange8u hal_ni_inRange8u ++#define cv_hal_inRange32f hal_ni_inRange32f ++//! @endcond ++ + //! @} + + +diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp +index 8c6d8ad9a9..47eb6fdb66 100644 +--- a/modules/core/src/minmax.cpp ++++ b/modules/core/src/minmax.cpp +@@ -1524,9 +1524,9 @@ void cv::minMaxIdx(InputArray _src, double* minVal, + { + // minIdx[0] and minIdx[0] are always 0 for "flatten" version + if (minIdx) +- ofs2idx(src, minIdx[1], minIdx); ++ ofs2idx(src, minIdx[1] + 1, minIdx); + if (maxIdx) +- ofs2idx(src, maxIdx[1], maxIdx); ++ ofs2idx(src, maxIdx[1] + 1, maxIdx); + return; + } + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) +diff --git a/modules/imgproc/src/smooth.dispatch.cpp b/modules/imgproc/src/smooth.dispatch.cpp +index d0f50a73bb..1c308887dc 100644 +--- a/modules/imgproc/src/smooth.dispatch.cpp ++++ b/modules/imgproc/src/smooth.dispatch.cpp +@@ -654,6 +654,25 @@ void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, + ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType) + ); + ++ { ++ Mat src = _src.getMat(); ++ Mat dst = _dst.getMat(); ++ ++ Point ofs; ++ Size wsz(src.cols, src.rows); ++ if(!(borderType & BORDER_ISOLATED)) ++ src.locateROI( wsz, ofs ); ++ ++ if (sigma1 == 0.0 && sigma2 == 0.0 && ksize.height == ksize.width) { ++ CALL_HAL(gaussianBlurBinomial, cv_hal_gaussianBlurBinomial, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn, ++ ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, borderType&~BORDER_ISOLATED); ++ } ++ ++ CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn, ++ ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height, ++ sigma1, sigma2, borderType&~BORDER_ISOLATED); ++ } ++ + if(sdepth == CV_8U && ((borderType & BORDER_ISOLATED) || !_src.isSubmatrix())) + { + std::vector fkx, fky; diff --git a/adapters/opencv/opencv-4.9.patch b/adapters/opencv/opencv-4.9.patch index 42897a636..6a1101574 100644 --- a/adapters/opencv/opencv-4.9.patch +++ b/adapters/opencv/opencv-4.9.patch @@ -1,4 +1,14 @@ // SPDX-FileCopyrightText: 2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright (C) 2000-2022, Intel Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2015-2023, OpenCV Foundation, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2008-2016, Itseez Inc., all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2023, Xperience AI, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and Robotics for Society, all rights reserved. +// SPDX-FileCopyrightText: Copyright (C) 2022-2023, Southern University of Science And Technology, all rights reserved. +// SPDX-FileCopyrightText: Third party copyrights are property of their respective owners. // // SPDX-License-Identifier: Apache-2.0 diff --git a/conformity/opencv/CMakeLists.txt b/conformity/opencv/CMakeLists.txt index b6f9666a8..3daa88943 100644 --- a/conformity/opencv/CMakeLists.txt +++ b/conformity/opencv/CMakeLists.txt @@ -9,7 +9,7 @@ project("OpenCV Conformity" CXX) set(CMAKE_CXX_STANDARD 17) # Please update SECURITY.md if adding, removing or changing the version of third party content. -set(OPENCV_VERSION "4.9.0" CACHE STRING "Version of OpenCV") +set(OPENCV_VERSION "4.10.0" CACHE STRING "Version of OpenCV") set(OPENCV_URL "https://github.com/opencv/opencv/archive/refs/tags/${OPENCV_VERSION}.tar.gz" CACHE STRING "URL of OpenCV") # Remove the last part of the version number (e.g., 4.9.0 -> 4.9) diff --git a/doc/build.md b/doc/build.md index 5906cd34c..69137b642 100644 --- a/doc/build.md +++ b/doc/build.md @@ -29,18 +29,20 @@ For details of which OpenCV function are accelerated by KleidiCV see ### Get and patch OpenCV source -KleidiCV is compatible with [OpenCV](https://opencv.org) version 4.9 and later. (OpenCV 5.x support is experimental.) +This version of KleidiCV is compatible with [OpenCV](https://opencv.org) version 4.10 and later. +Earlier versions of KleidiCV are compatible with earlier versions of OpenCV. +OpenCV 5.x support is experimental. Integration consists of the following steps: 1. Download OpenCV sources: ``` -wget https://github.com/opencv/opencv/archive/refs/tags/4.9.0.tar.gz -tar xf 4.9.0.tar.gz -cd opencv-4.9.0 +wget https://github.com/opencv/opencv/archive/refs/tags/4.10.0.tar.gz +tar xf 4.10.0.tar.gz +cd opencv-4.10.0 ``` 2. Patch OpenCV: ``` -patch -p1