Skip to content

Commit d031ffd

Browse files
committed
Merge branch 4.x
2 parents b55bf35 + 91c38c9 commit d031ffd

File tree

7 files changed

+143
-1
lines changed

7 files changed

+143
-1
lines changed

modules/cudafilters/include/opencv2/cudafilters.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ center.
9797
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
9898
@param borderVal Default border value.
9999
100+
@note
101+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
102+
100103
@sa boxFilter
101104
*/
102105
CV_EXPORTS_W Ptr<Filter> createBoxFilter(int srcType, int dstType, Size ksize, Point anchor = Point(-1, -1),
@@ -115,6 +118,9 @@ center.
115118
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
116119
@param borderVal Default border value.
117120
121+
@note
122+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
123+
118124
@sa filter2D
119125
*/
120126
CV_EXPORTS_W Ptr<Filter> createLinearFilter(int srcType, int dstType, InputArray kernel, Point anchor = Point(-1, -1),
@@ -134,6 +140,9 @@ applied (see getDerivKernels ).
134140
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
135141
@param borderVal Default border value.
136142
143+
@note
144+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
145+
137146
@sa Laplacian
138147
*/
139148
CV_EXPORTS_W Ptr<Filter> createLaplacianFilter(int srcType, int dstType, int ksize = 1, double scale = 1,
@@ -156,6 +165,9 @@ the aperture center.
156165
borderInterpolate.
157166
@param columnBorderMode Pixel extrapolation method in the horizontal direction.
158167
168+
@note
169+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
170+
159171
@sa sepFilter2D
160172
*/
161173
CV_EXPORTS_W Ptr<Filter> createSeparableLinearFilter(int srcType, int dstType, InputArray rowKernel, InputArray columnKernel,
@@ -178,6 +190,9 @@ applied. For details, see getDerivKernels .
178190
@param rowBorderMode Pixel extrapolation method in the vertical direction. For details, see
179191
borderInterpolate.
180192
@param columnBorderMode Pixel extrapolation method in the horizontal direction.
193+
194+
@note
195+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
181196
*/
182197
CV_EXPORTS_W Ptr<Filter> createDerivFilter(int srcType, int dstType, int dx, int dy,
183198
int ksize, bool normalize = false, double scale = 1,
@@ -196,6 +211,9 @@ applied. For details, see getDerivKernels .
196211
borderInterpolate.
197212
@param columnBorderMode Pixel extrapolation method in the horizontal direction.
198213
214+
@note
215+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
216+
199217
@sa Sobel
200218
*/
201219
CV_EXPORTS_W Ptr<Filter> createSobelFilter(int srcType, int dstType, int dx, int dy, int ksize = 3,
@@ -213,6 +231,9 @@ applied. See getDerivKernels for details.
213231
borderInterpolate.
214232
@param columnBorderMode Pixel extrapolation method in the horizontal direction.
215233
234+
@note
235+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
236+
216237
@sa Scharr
217238
*/
218239
CV_EXPORTS_W Ptr<Filter> createScharrFilter(int srcType, int dstType, int dx, int dy,
@@ -233,6 +254,9 @@ CV_EXPORTS_W Ptr<Filter> createScharrFilter(int srcType, int dstType, int dx, in
233254
borderInterpolate.
234255
@param columnBorderMode Pixel extrapolation method in the horizontal direction.
235256
257+
@note
258+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
259+
236260
@sa GaussianBlur
237261
*/
238262
CV_EXPORTS_W Ptr<Filter> createGaussianFilter(int srcType, int dstType, Size ksize,
@@ -258,6 +282,9 @@ CV_EXPORTS_W Ptr<Filter> createGaussianFilter(int srcType, int dstType, Size ksi
258282
is at the center.
259283
@param iterations Number of times erosion and dilation to be applied.
260284
285+
@note
286+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
287+
261288
@sa morphologyEx
262289
*/
263290
CV_EXPORTS_W Ptr<Filter> createMorphologyFilter(int op, int srcType, InputArray kernel, Point anchor = Point(-1, -1), int iterations = 1);
@@ -272,6 +299,9 @@ CV_EXPORTS_W Ptr<Filter> createMorphologyFilter(int op, int srcType, InputArray
272299
@param anchor Anchor point. The default value (-1) means that the anchor is at the kernel center.
273300
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
274301
@param borderVal Default border value.
302+
303+
@note
304+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
275305
*/
276306
CV_EXPORTS_W Ptr<Filter> createBoxMaxFilter(int srcType, Size ksize,
277307
Point anchor = Point(-1, -1),
@@ -284,6 +314,9 @@ CV_EXPORTS_W Ptr<Filter> createBoxMaxFilter(int srcType, Size ksize,
284314
@param anchor Anchor point. The default value (-1) means that the anchor is at the kernel center.
285315
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
286316
@param borderVal Default border value.
317+
318+
@note
319+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
287320
*/
288321
CV_EXPORTS_W Ptr<Filter> createBoxMinFilter(int srcType, Size ksize,
289322
Point anchor = Point(-1, -1),
@@ -300,6 +333,9 @@ CV_EXPORTS_W Ptr<Filter> createBoxMinFilter(int srcType, Size ksize,
300333
@param anchor Anchor point. The default value (-1) means that the anchor is at the kernel center.
301334
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
302335
@param borderVal Default border value.
336+
337+
@note
338+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
303339
*/
304340
CV_EXPORTS_W Ptr<Filter> createRowSumFilter(int srcType, int dstType, int ksize, int anchor = -1, int borderMode = BORDER_DEFAULT, Scalar borderVal = Scalar::all(0));
305341

@@ -311,6 +347,9 @@ CV_EXPORTS_W Ptr<Filter> createRowSumFilter(int srcType, int dstType, int ksize,
311347
@param anchor Anchor point. The default value (-1) means that the anchor is at the kernel center.
312348
@param borderMode Pixel extrapolation method. For details, see borderInterpolate .
313349
@param borderVal Default border value.
350+
351+
@note
352+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
314353
*/
315354
CV_EXPORTS_W Ptr<Filter> createColumnSumFilter(int srcType, int dstType, int ksize, int anchor = -1, int borderMode = BORDER_DEFAULT, Scalar borderVal = Scalar::all(0));
316355

@@ -329,6 +368,9 @@ Outputs an image that has been filtered using a median-filtering formulation.
329368
Details on this algorithm can be found in:
330369
Green, O., 2017. "Efficient scalable median filtering using histogram-based operations",
331370
IEEE Transactions on Image Processing, 27(5), pp.2217-2228.
371+
372+
@note
373+
If applied in a CUDA Stream, a distinct filter instance must be created for each Stream. Sharing a single instance across multiple streams is unsupported and may lead to undefined behavior due to stream-specific internal state.
332374
*/
333375
CV_EXPORTS_W Ptr<Filter> createMedianFilter(int srcType, int windowSize, int partition = 128);
334376

modules/cudawarping/include/opencv2/cudawarping.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ CV_EXPORTS_W void resize(InputArray src, OutputArray dst, Size dsize, double fx=
118118
@param src Source image. CV_8U , CV_16U , CV_32S , or CV_32F depth and 1, 3, or 4 channels are
119119
supported.
120120
@param dst Destination image with the same type as src . The size is dsize .
121+
**In-place operation (src == dst) is not supported and will result in an error.**
121122
@param M *2x3* Mat or UMat transformation matrix.
122123
@param dsize Size of the destination image.
123124
@param flags Combination of interpolation methods (see resize) and the optional flag
@@ -127,6 +128,7 @@ INTER_NEAREST , INTER_LINEAR , and INTER_CUBIC interpolation methods are support
127128
@param borderValue
128129
@param stream Stream for the asynchronous version.
129130
131+
@note In-place operation is not supported. If src and dst refer to the same data, the behavior is undefined.
130132
@sa warpAffine
131133
*/
132134
CV_EXPORTS void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR,

modules/cudawarping/src/warp.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ void cv::cuda::warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size
208208
_dst.create(dsize, src.type());
209209
GpuMat dst = _dst.getGpuMat();
210210

211+
CV_Assert( src.data != dst.data && "In-place operation not supported for cv::cuda::warpAffine" );
212+
211213
Size wholeSize;
212214
Point ofs;
213215
src.locateROI(wholeSize, ofs);

modules/cudawarping/test/test_warp_affine.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,36 @@ CUDA_TEST_P(WarpAffine, Accuracy)
222222
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-1 : 1.0);
223223
}
224224

225+
CUDA_TEST_P(WarpAffine, OverlapDetection)
226+
{
227+
cv::Mat src = randomMat(size, type);
228+
ASSERT_FALSE(src.empty());
229+
cv::cuda::GpuMat gpuSrc;
230+
gpuSrc.upload(src);
231+
232+
cv::Mat M = cv::Mat::eye(2, 3, CV_64FC1);
233+
int flags = interpolation;
234+
if (inverse)
235+
flags |= cv::WARP_INVERSE_MAP;
236+
237+
{
238+
cv::cuda::GpuMat gpuDst(gpuSrc, cv::Rect(0, 0, size.width, size.height));
239+
240+
EXPECT_THROW(
241+
cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0)),
242+
cv::Exception);
243+
}
244+
245+
{
246+
cv::cuda::GpuMat gpuDst(size, gpuSrc.type());
247+
ASSERT_NE(gpuSrc.data, gpuDst.data); // Confirm they are distinct
248+
249+
EXPECT_NO_THROW({
250+
cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0));
251+
});
252+
}
253+
}
254+
225255
INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffine, testing::Combine(
226256
ALL_DEVICES,
227257
DIFFERENT_SIZES,

modules/gapi/include/opencv2/gapi/infer/ov.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct ParamDesc {
6666
LayerVariantAttr<std::vector<float>> scale_values;
6767

6868
LayerVariantAttr<int> interpolation;
69+
70+
bool clamp_outputs = false;
6971
};
7072

7173
struct CompiledModel {
@@ -356,6 +358,24 @@ template<typename Net> struct Params {
356358
return *this;
357359
}
358360

361+
/** @brief Enables or disables clamping of model outputs in the PrePostProcessor.
362+
363+
By default, output values are clamped to the valid range for the output precision
364+
by the device or plugin. Enabling this option moves clamping to the PrePostProcessor stage.
365+
366+
@note This feature is only available with OpenVINO 2025.2 and newer.
367+
368+
@param flag If true, clamping is performed in the PrePostProcessor;
369+
otherwise, it is handled by the device or plugin.
370+
@return reference to this parameter structure.
371+
*/
372+
Params<Net>&
373+
cfgClampOutputs(bool flag = true) {
374+
detail::getModelToSetAttrOrThrow(m_desc.kind, "clamp outputs")
375+
.clamp_outputs = std::move(flag);
376+
return *this;
377+
}
378+
359379
/** @brief Specifies the new shape for input layers.
360380
361381
The function is used to set new shape for input layers.
@@ -625,6 +645,14 @@ class Params<cv::gapi::Generic> {
625645
return *this;
626646
}
627647

648+
/** @see ov::Params::cfgClampOutputs. */
649+
Params&
650+
cfgClampOutputs(bool flag = true) {
651+
detail::getModelToSetAttrOrThrow(m_desc.kind, "clamp outputs")
652+
.clamp_outputs = std::move(flag);
653+
return *this;
654+
}
655+
628656
/** @see ov::Params::cfgReshape. */
629657
Params& cfgReshape(std::vector<size_t> new_shape) {
630658
detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape")

modules/gapi/src/backends/ov/govbackend.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,25 @@ static int toCV(const ov::element::Type &type) {
147147
return -1;
148148
}
149149

150+
static inline std::pair<double, double> get_CV_type_range(int cv_type) {
151+
switch (cv_type) {
152+
case CV_8U:
153+
return { static_cast<double>(std::numeric_limits<uint8_t>::min()),
154+
static_cast<double>(std::numeric_limits<uint8_t>::max()) };
155+
case CV_32S:
156+
return { static_cast<double>(std::numeric_limits<int32_t>::min()),
157+
static_cast<double>(std::numeric_limits<int32_t>::max()) };
158+
case CV_32F:
159+
return { static_cast<double>(std::numeric_limits<float>::lowest()),
160+
static_cast<double>(std::numeric_limits<float>::max()) };
161+
case CV_16F:
162+
return { -65504.0, 65504.0 };
163+
default:
164+
GAPI_Error("OV Backend: Unsupported data type");
165+
}
166+
return {0.0, 0.0};
167+
}
168+
150169
static void copyFromOV(const ov::Tensor &tensor, cv::Mat &mat) {
151170
const auto total = mat.total() * mat.channels();
152171
if (toCV(tensor.get_element_type()) != mat.depth() ||
@@ -1052,6 +1071,20 @@ class PrePostProcWrapper {
10521071
if (explicit_out_tensor_prec) {
10531072
m_ppp.output(output_name).tensor()
10541073
.set_element_type(toOV(*explicit_out_tensor_prec));
1074+
1075+
if (m_model_info.clamp_outputs) {
1076+
#if INF_ENGINE_RELEASE >= 2025020000
1077+
auto clamp_range = get_CV_type_range(*explicit_out_tensor_prec);
1078+
m_ppp.output(output_name).postprocess()
1079+
.clamp(clamp_range.first, clamp_range.second);
1080+
#else
1081+
static bool warned = false;
1082+
if (!warned) {
1083+
GAPI_LOG_WARNING(NULL, "cfgClampOutputs is enabled, but not supported in this OpenVINO version. Clamping will be ignored.");
1084+
warned = true;
1085+
}
1086+
#endif // INF_ENGINE_RELEASE >= 2025020000
1087+
}
10551088
}
10561089
}
10571090
}

modules/videostab/src/cuda/global_motion.cu

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ namespace cv { namespace cuda { namespace device { namespace globmotion {
5252
__constant__ float cml[9];
5353
__constant__ float cmr[9];
5454

55+
struct is_zero
56+
{
57+
__host__ __device__ bool operator()(uchar x) const { return x == 0; }
58+
};
59+
5560
int compactPoints(int N, float *points0, float *points1, const uchar *mask)
5661
{
5762
thrust::device_ptr<float2> dpoints0((float2*)points0);
@@ -60,7 +65,7 @@ int compactPoints(int N, float *points0, float *points1, const uchar *mask)
6065

6166
return (int)(thrust::remove_if(thrust::make_zip_iterator(thrust::make_tuple(dpoints0, dpoints1)),
6267
thrust::make_zip_iterator(thrust::make_tuple(dpoints0 + N, dpoints1 + N)),
63-
dmask, thrust::not1(thrust::identity<uchar>()))
68+
dmask, is_zero())
6469
- thrust::make_zip_iterator(make_tuple(dpoints0, dpoints1)));
6570
}
6671

0 commit comments

Comments
 (0)