nareshmlx/opencv-pr huggingface dataset:
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 249

**Code Changes:**
```diff
+        cv::gapi::own::ThreadPool& tp;
+        cv::gapi::own::Latch& latch;
+    };
+
+    void run(ExecutionState& state);
+    bool isLast() const { return m_consumers.empty();  }
+    void reset()        { m_ready_producers.store(0u); }
+
+private:
+    TaskManager::F           m_f;
+    const uint32_t           m_num_producers;
```

Review comment:
Could there be a data race for the vector of consumers here?
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 249

**Code Changes:**
```diff
+        cv::gapi::own::ThreadPool& tp;
+        cv::gapi::own::Latch& latch;
+    };
+
+    void run(ExecutionState& state);
+    bool isLast() const { return m_consumers.empty();  }
+    void reset()        { m_ready_producers.store(0u); }
+
+private:
+    TaskManager::F           m_f;
+    const uint32_t           m_num_producers;
```

Review comment:
Once all tasks are created, `m_consumers` aren't changed, so different threads only perform read operations. Not obvious though
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 309

**Code Changes:**
```diff
+    // Reset the number of ready dependencies for all tasks
+    for (auto& task : m_all_tasks) { task->reset(); }
+
+    // Count the number of last tasks
+    auto isLast = [](const std::shared_ptr<Task>& task) { return task->isLast(); };
+    const auto kNumLastsTasks =
+        std::count_if(m_all_tasks.begin(), m_all_tasks.end(), isLast);
+
+    // Initialize the latch, schedule initial tasks
+    // and wait until all lasts tasks are done
+    cv::gapi::own::Latch latch(kNumLastsTasks);
```

Review comment:
Not sure what means "recursive" task creation, could you elaborate, please?
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 274

**Code Changes:**
```diff
+    // Execute the task
+    m_f();
+    // Notify every consumer about completion one of its dependencies
+    for (auto* consumer : m_consumers) {
+        const auto num_ready =
+            consumer->m_ready_producers.fetch_add(1, std::memory_order_relaxed) + 1;
+        // The last completed producer schedule the consumer for execution
+        if (num_ready == consumer->m_num_producers) {
+            state.tp.schedule([&state, consumer](){
+                consumer->run(state);
+            });
```

Review comment:
It's a good question, I'd say we need to guarantee that the new scheduled task will see all changes in `magazine` that have been made by its producers which means `memory_order_acq_rel`. But since all `magazine` changes currently synchronized by `mutex` it's already guaranteed so `memory_order_relaxed` can be used until we get rid of the `mutex` on `magazine` :)
**File:** modules/gapi/include/opencv2/gapi/gcommon.hpp
**Change Type:** modified
**Context:** PR #24845: G-API: Implement concurrent executor

**Code Changes:**
```diff
@@ -263,12 +263,32 @@ struct graph_dump_path
 };
 /** @} */
 
+/**
+ * @brief Ask G-API to use threaded executor when cv::GComputation
+ * is compiled via cv::GComputation::compile method.
+ *
+ * Specifies a number of threads that should be used by executor.
+ */
```

Review comment:
> Can't we just declare it here and move implementation to a cpp file? In this case it's needed to call `cv::getNumThreads()` in header anyway
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 274

**Code Changes:**
```diff
+    // Execute the task
+    m_f();
+    // Notify every consumer about completion one of its dependencies
+    for (auto* consumer : m_consumers) {
+        const auto num_ready =
+            consumer->m_ready_producers.fetch_add(1, std::memory_order_relaxed) + 1;
+        // The last completed producer schedule the consumer for execution
+        if (num_ready == consumer->m_num_producers) {
+            state.tp.schedule([&state, consumer](){
+                consumer->run(state);
+            });
```

Review comment:
i'd vote for `++(int)` still as to a more concise construct. BUT that's up to you
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 309

**Code Changes:**
```diff
+    // Reset the number of ready dependencies for all tasks
+    for (auto& task : m_all_tasks) { task->reset(); }
+
+    // Count the number of last tasks
+    auto isLast = [](const std::shared_ptr<Task>& task) { return task->isLast(); };
+    const auto kNumLastsTasks =
+        std::count_if(m_all_tasks.begin(), m_all_tasks.end(), isLast);
+
+    // Initialize the latch, schedule initial tasks
+    // and wait until all lasts tasks are done
+    cv::gapi::own::Latch latch(kNumLastsTasks);
```

Review comment:
when tasks may spawn new (previously unknown) tasks, I believe. May be the case with loops, but let's put it aside for now
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 309

**Code Changes:**
```diff
+    // Reset the number of ready dependencies for all tasks
+    for (auto& task : m_all_tasks) { task->reset(); }
+
+    // Count the number of last tasks
+    auto isLast = [](const std::shared_ptr<Task>& task) { return task->isLast(); };
+    const auto kNumLastsTasks =
+        std::count_if(m_all_tasks.begin(), m_all_tasks.end(), isLast);
+
+    // Initialize the latch, schedule initial tasks
+    // and wait until all lasts tasks are done
+    cv::gapi::own::Latch latch(kNumLastsTasks);
```

Review comment:
The `Task` itself is an abstraction which handles dependencies so if it spawns new tasks recursively it's already taken into account...
**File:** modules/gapi/src/executor/gthreadedexecutor.cpp
**Change Type:** added
**Context:** PR #24845: G-API: Implement concurrent executor
**Review Line:** 274

**Code Changes:**
```diff
+    // Execute the task
+    m_f();
+    // Notify every consumer about completion one of its dependencies
+    for (auto* consumer : m_consumers) {
+        const auto num_ready =
+            consumer->m_ready_producers.fetch_add(1, std::memory_order_relaxed) + 1;
+        // The last completed producer schedule the consumer for execution
+        if (num_ready == consumer->m_num_producers) {
+            state.tp.schedule([&state, consumer](){
+                consumer->run(state);
+            });
```

Review comment:
The thing is `operator++(int)` doesn't accept `std::memory_order` which isn't default there so I can't use it :)
**File:** modules/core/src/system.cpp
**Change Type:** modified
**Context:** PR #24868: fix qnx-sdp-700 build
**Review Line:** 131

**Code Changes:**
```diff
@@ -128,7 +128,7 @@ void* allocSingletonNewBuffer(size_t size) { return malloc(size); }
 #  include <sys/auxv.h>
 using Elf64_auxv_t = auxv64_t;
 #  include <elfdefinitions.h>
-constexpr decltype(auto) AT_HWCAP = NT_GNU_HWCAP;
+const uint64_t AT_HWCAP = NT_GNU_HWCAP;
 #else
 #  include <elf.h>
 #endif
```

Review comment:
Thank for review, fixed now.
**File:** modules/java/generator/android-21/java/org/opencv/android/JavaCamera2View.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 342

**Code Changes:**
```diff
             if (mFpsMeter != null) {
                 mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
             }
+
+            Log.i(LOGTAG, "Opening camera: " + mCameraID);
+            manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
+        } catch (CameraAccessException e) {
+            Log.e(LOGTAG, "OpenCamera - Camera Access Exception", e);
         } catch (RuntimeException e) {
             throw new RuntimeException("Interrupted while setCameraPreviewSize.", e);
         }
```

Review comment:
Moved camera starting here, because preview size should be defined before camera start
**File:** modules/java/generator/android-21/java/org/opencv/android/JavaCamera2View.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 325

**Code Changes:**
```diff
@@ -46,6 +46,7 @@ public class JavaCamera2View extends CameraBridgeViewBase {
     protected ImageReader mImageReader;
     protected int mPreviewFormat = ImageFormat.YUV_420_888;
     protected int mRequestTemplate = CameraDevice.TEMPLATE_PREVIEW;
+    private int mFrameRotation;
 
     protected CameraDevice mCameraDevice;
     protected CameraCaptureSession mCaptureSession;
@@ -86,8 +87,8 @@ private void stopBackgroundThread() {
         }
     }
 
-    protected boolean initializeCamera() {
-        Log.i(LOGTAG, "initializeCamera");
+    protected boolean selectCamera() {
```

Review comment:
There is already a createCameraPreviewSession call in onOpened camera callback.
**File:** modules/java/generator/android-21/java/org/opencv/android/JavaCamera2View.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 216

**Code Changes:**
```diff
                     assert (image.getFormat() == mPreviewFormat);
 
-                    JavaCamera2Frame tempFrame = new JavaCamera2Frame(image);
+                    RotatedCameraFrame tempFrame = new RotatedCameraFrame(new JavaCamera2Frame(image), mFrameRotation);
                     deliverAndDrawFrame(tempFrame);
+                    tempFrame.mFrame.release();
                     tempFrame.release();
                     image.close();
                 }
@@ -303,11 +302,22 @@ boolean calcPreviewSize(final int width, final int height) {
     protected boolean connectCamera(int width, int height) {
```

Review comment:
I think it should be moved inside RotatedCameraFrame.release().
**File:** modules/java/generator/android-24/java/org/opencv/android/NativeCameraView.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.

**Code Changes:**
```diff
@@ -10,6 +10,7 @@
 import org.opencv.videoio.VideoWriter;
 
 import android.content.Context;
+import android.hardware.Camera;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ViewGroup.LayoutParams;
@@ -25,7 +26,7 @@ public class NativeCameraView extends CameraBridgeViewBase {
     private Thread mThread;
```

Review comment:
Looks like you can re-use CameraInfo from cameras iteration when camera is selected.
**File:** modules/java/generator/android/java/org/opencv/android/JavaCameraView.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 252

**Code Changes:**
```diff
                         mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
@@ -245,7 +249,9 @@ protected void releaseCamera() {
                 mFrameChain[1].release();
             }
             if (mCameraFrame != null) {
+                mCameraFrame[0].mFrame.release();
                 mCameraFrame[0].release();
+                mCameraFrame[1].mFrame.release();
                 mCameraFrame[1].release();
             }
         }
```

Review comment:
The same idea on release()
**File:** modules/java/generator/android-24/java/org/opencv/android/NativeCameraView.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 173

**Code Changes:**
```diff
 
     private void releaseCamera() {
         synchronized (this) {
-            if (mFrame != null) mFrame.release();
+            if (mFrame != null) {
+                mFrame.mFrame.release();
+                mFrame.release();
+            }
             if (mCamera != null) mCamera.release();
         }
     }
```

Review comment:
The same for release()
**File:** modules/java/generator/android-21/java/org/opencv/android/JavaCamera2View.java
**Change Type:** modified
**Context:** PR #24869: Added screen rotation support to JavaCamera2View amd NativeCameraView. Fixed JavaCamera2View initialization.
**Review Line:** 216

**Code Changes:**
```diff
                     assert (image.getFormat() == mPreviewFormat);
 
-                    JavaCamera2Frame tempFrame = new JavaCamera2Frame(image);
+                    RotatedCameraFrame tempFrame = new RotatedCameraFrame(new JavaCamera2Frame(image), mFrameRotation);
                     deliverAndDrawFrame(tempFrame);
+                    tempFrame.mFrame.release();
                     tempFrame.release();
                     image.close();
                 }
@@ -303,11 +302,22 @@ boolean calcPreviewSize(final int width, final int height) {
     protected boolean connectCamera(int width, int height) {
```

Review comment:
I thought about this too, but I think it is not good to release an object inside a class if the object is created outside. RotatedCameraFrame constructor takes a pointer to existing JavaCamera2Frame object, and this object may be used in other place.
**File:** modules/core/include/opencv2/core/cvdef.h
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...

**Code Changes:**
```diff
@@ -751,88 +751,43 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ   (EnumType, EnumType)
 
 
 /****************************************************************************************\
-*                      CV_NODISCARD attribute (deprecated, GCC only)                     *
-* DONT USE: use instead the standard CV_NODISCARD_STD macro above                        *
-*           this legacy method silently fails to issue warning until some version        *
-*           after gcc 6.3.0. Yet with gcc 7+ you can use the above standard method       *
-*           which makes this method useless. Don't use it.                               *
-* @deprecated use instead CV_NODISCARD_STD                                               *
```

Review comment:
Something is still wrong with VS 2015. Maybe change it to MSVC version check (removed line 773): `defined(_MSC_VER) && _MSC_VER < 1800`
**File:** modules/core/include/opencv2/core/cvdef.h
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...
**Review Line:** 764

**Code Changes:**
```diff
+// <https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus>
+#  if defined(_MSC_VER)
+#    if _MSC_VER < 1800
+#      error "OpenCV 4.x+ requires enabled C++11 support"
 #    endif
+#  elif __cplusplus < 201103L
+#    error "OpenCV 4.x+ requires enabled C++11 support"
 #  endif
 #endif
-#ifndef CV_NODISCARD
-#  define CV_NODISCARD /* nothing by default */
```

Review comment:
It still does not work, first condition passes, but second condition still fails. ``` C:\build\precommit_windows64\4.x\opencv\modules\core\include\opencv2/core/cvdef.h(757): fatal error C1189: #error: "OpenCV 4.x+ requires enabled C++11 support" ``` Should be something like this: ```.cpp #if GOOD_MSVC_VERSION // ok #elif BAD_MSVC_VERSION || BAD_CPLUSPLUS_VERSION // error #endif ``` How can it be optimized :thinking: ?
**File:** modules/core/include/opencv2/core/cvdef.h
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...
**Review Line:** 764

**Code Changes:**
```diff
+// <https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus>
+#  if defined(_MSC_VER)
+#    if _MSC_VER < 1800
+#      error "OpenCV 4.x+ requires enabled C++11 support"
 #    endif
+#  elif __cplusplus < 201103L
+#    error "OpenCV 4.x+ requires enabled C++11 support"
 #  endif
 #endif
-#ifndef CV_NODISCARD
-#  define CV_NODISCARD /* nothing by default */
```

Review comment:
Maybe: ```.cpp #if MSVC #if BAD_VERSION // error #endif #elif BAD_CPLUSPLUS // error #endif ```
**File:** modules/core/include/opencv2/core/cvdef.h
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...
**Review Line:** 764

**Code Changes:**
```diff
+// <https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus>
+#  if defined(_MSC_VER)
+#    if _MSC_VER < 1800
+#      error "OpenCV 4.x+ requires enabled C++11 support"
 #    endif
+#  elif __cplusplus < 201103L
+#    error "OpenCV 4.x+ requires enabled C++11 support"
 #  endif
 #endif
-#ifndef CV_NODISCARD
-#  define CV_NODISCARD /* nothing by default */
```

Review comment:
Yes, that makes sense; done. Sorry this is taking a few iterations, like I said, I don't have MSVC locally. :)
**File:** doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...

**Code Changes:**
```diff
@@ -9,6 +9,9 @@ How to use the OpenCV parallel_for_ to parallelize your code {#tutorial_how_to_u
 | -: | :- |
 | Compatibility | OpenCV >= 3.0 |
 
+
+@note See also C++ lambda usage with parallel for in [tuturial](@ref tutorial_how_to_use_OpenCV_parallel_for_new).
+
 Goal
 ----
 
```

Review comment:
Please restore `setNumThreads` related description.
**File:** samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_new.cpp
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...

**Code Changes:**
```diff
@@ -4,6 +4,8 @@
 #include <opencv2/imgproc.hpp>
 #include <opencv2/highgui.hpp>
 
+#define PARALLEL_FOR_LAMBDA
+
 using namespace std;
 using namespace cv;
 
@@ -47,7 +49,8 @@ void conv_seq(Mat src, Mat &dst, Mat kernel)
```

Review comment:
There is reference to `overload-full` block in markdown.
**File:** samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_new.cpp
**Change Type:** modified
**Context:** PR #23736: Removed all pre-C++11 code, workarounds, and branches - This removes a bunch of pre-C++11 workrarounds that are no longer necessary as C++1...

**Code Changes:**
```diff
@@ -4,6 +4,8 @@
 #include <opencv2/imgproc.hpp>
 #include <opencv2/highgui.hpp>
 
+#define PARALLEL_FOR_LAMBDA
+
 using namespace std;
 using namespace cv;
 
@@ -47,7 +49,8 @@ void conv_seq(Mat src, Mat &dst, Mat kernel)
```

Review comment:
The same. See CI warnings.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #24809: Added test for YOLO NAS
**Review Line:** 2771

**Code Changes:**
```diff
     }
@@ -2751,6 +2768,41 @@ TEST_P(Test_ONNX_nets, YOLOX)
         1.0e-4, 1.0e-4);
 }
 
+TEST_P(Test_ONNX_nets, YOLONas)
+{
+    // model information: https://dl.opencv.org/models/yolo-nas/Readme.md
+    std::string weightPath = _tf("models/yolo_nas_s.onnx", false);
+
+    Size targetSize{640, 640};
```

Review comment:
Concat_2 and some others have axis=-1. ONNX documentation " axis : int (required) Which axis to concat on. A negative value means counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(inputs).. ". Looks like we need to add the option for Concat first.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #24809: Added test for YOLO NAS
**Review Line:** 2771

**Code Changes:**
```diff
     }
@@ -2751,6 +2768,41 @@ TEST_P(Test_ONNX_nets, YOLOX)
         1.0e-4, 1.0e-4);
 }
 
+TEST_P(Test_ONNX_nets, YOLONas)
+{
+    // model information: https://dl.opencv.org/models/yolo-nas/Readme.md
+    std::string weightPath = _tf("models/yolo_nas_s.onnx", false);
+
+    Size targetSize{640, 640};
```

Review comment:
Fixed in https://github.com/opencv/opencv/pull/24865
**File:** cmake/OpenCVDetectPython.cmake
**Change Type:** modified
**Context:** PR #24860: Downgrade LIMITED_API_VERSION, if python3 is older than 3.6

**Code Changes:**
```diff
@@ -295,7 +295,12 @@ find_python("${OPENCV_PYTHON3_VERSION}" "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYT
 OCV_OPTION(PYTHON3_LIMITED_API "Build with Python Limited API (not available with numpy >=1.15 <1.17)" NO
            VISIBLE_IF PYTHON3_NUMPY_VERSION VERSION_LESS "1.15" OR NOT PYTHON3_NUMPY_VERSION VERSION_LESS "1.17")
 if(PYTHON3_LIMITED_API)
-  set(PYTHON3_LIMITED_API_VERSION "0x03060000" CACHE STRING "Minimal Python version for Limited API")
+  set(_default_ver "0x03060000")
+  if(PYTHON3_VERSION_STRING VERSION_LESS "3.6")
+    # fix for older pythons
+    set(_default_ver "0x030${PYTHON3_VERSION_MINOR}0000")
+  endif()
```

Review comment:
Which CMake version supports conditionals in `set()`?
**File:** cmake/OpenCVDetectPython.cmake
**Change Type:** modified
**Context:** PR #24860: Downgrade LIMITED_API_VERSION, if python3 is older than 3.6

**Code Changes:**
```diff
@@ -295,7 +295,12 @@ find_python("${OPENCV_PYTHON3_VERSION}" "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYT
 OCV_OPTION(PYTHON3_LIMITED_API "Build with Python Limited API (not available with numpy >=1.15 <1.17)" NO
            VISIBLE_IF PYTHON3_NUMPY_VERSION VERSION_LESS "1.15" OR NOT PYTHON3_NUMPY_VERSION VERSION_LESS "1.17")
 if(PYTHON3_LIMITED_API)
-  set(PYTHON3_LIMITED_API_VERSION "0x03060000" CACHE STRING "Minimal Python version for Limited API")
+  set(_default_ver "0x03060000")
+  if(PYTHON3_VERSION_STRING VERSION_LESS "3.6")
+    # fix for older pythons
+    set(_default_ver "0x030${PYTHON3_VERSION_MINOR}0000")
+  endif()
```

Review comment:
Perhaps it would be more readable to use negative condition (+avoid docstring duplication): ```.cmake set(_default_ver "0x03060000") if(${PYTHON}_VERSION_STRING VERSION_LESS "3.6") # fix for older pythons set(_default_ver "0x030${PYTHON3_VERSION_MINOR}0000") endif() set(PYTHON3_LIMITED_API_VERSION ${_default_ver} CACHE STRING "Minimal Python version for Limited API") ```
**File:** cmake/OpenCVDetectPython.cmake
**Change Type:** modified
**Context:** PR #24860: Downgrade LIMITED_API_VERSION, if python3 is older than 3.6

**Code Changes:**
```diff
@@ -295,7 +295,12 @@ find_python("${OPENCV_PYTHON3_VERSION}" "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYT
 OCV_OPTION(PYTHON3_LIMITED_API "Build with Python Limited API (not available with numpy >=1.15 <1.17)" NO
            VISIBLE_IF PYTHON3_NUMPY_VERSION VERSION_LESS "1.15" OR NOT PYTHON3_NUMPY_VERSION VERSION_LESS "1.17")
 if(PYTHON3_LIMITED_API)
-  set(PYTHON3_LIMITED_API_VERSION "0x03060000" CACHE STRING "Minimal Python version for Limited API")
+  set(_default_ver "0x03060000")
+  if(PYTHON3_VERSION_STRING VERSION_LESS "3.6")
+    # fix for older pythons
+    set(_default_ver "0x030${PYTHON3_VERSION_MINOR}0000")
+  endif()
```

Review comment:
unrelated change