# Python CUDA operations on matrices not working with scalars

**URL:** <https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065>\
**Category:** Python\
**Tags:** cuda, cudaarithm\
**Created:** [October 22, 2024, 1:24pm UTC](https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065 "2024-10-22T13:24:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mminervini](https://avatars.discourse-cdn.com/v4/letter/m/f05b48/32.png) [@mminervini](https://forum.opencv.org/u/mminervini)\
**Post date:** [October 22, 2024, 1:24pm UTC](https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065/1 "2024-10-22T13:24:03Z")

</div>

Per element CUDA operations such as `cv::cuda::divide` or `cv::cuda::multiply` in C++ can be applied to a matrix-matrix input as well as to a matrix-scalar input.  
In fact, the following C++ code compiles flawlessly:

```auto
cv::Mat test;
cv::cuda::GpuMat cu_test(4, 4, CV_8UC1, 16);
cu_test.download(test);
std::cout << test << std::endl;
cv::cuda::divide(cu_test, 2, cu_test);
cu_test.download(test);
std::cout << test << std::endl;

```

And as expected outputs:

```auto
[ 16, 16, 16, 16;
  16, 16, 16, 16;
  16, 16, 16, 16;
  16, 16, 16, 16]
[ 8, 8, 8, 8;
   8, 8, 8, 8;
   8, 8, 8, 8;
   8, 8, 8, 8]

```

On the other hand, the same logic doesn’t work in Python.  
For example, the Python equivalent of the above C++ code:

```auto
cu_test = cv2.cuda_GpuMat(4, 4, cv2.CV_8UC1, 16)
test = cu_test.download()
print(test)
cu_test = cv2.cuda.divide(cu_test, 2)
test = cu_test.download()
print(test)

```

Fails as at `cv2.cuda.divide`:

```auto
[[16 16 16 16]
 [16 16 16 16]
 [16 16 16 16]
 [16 16 16 16]]
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    cu_test = cv2.cuda.divide(cu_test, 2)
cv2.error: OpenCV(4.10.0) :-1: error: (-5:Bad argument) in function 'divide'
> Overload resolution failed:
> - src1 is not a numpy array, neither a scalar
> - Expected Ptr<cv::cuda::GpuMat> for argument 'src2'
> - Expected Ptr<cv::UMat> for argument 'src1'

```

According to `help(cv2.cuda.divide)` a matrix-scalar division is supposed to work:

```auto
divide(...)
    divide(src1, src2[, dst[, scale[, dtype[, stream]]]]) -> dst
    . @brief Computes a matrix-matrix or matrix-scalar division.
    .   
    . @param src1 First source matrix or a scalar.
    . @param src2 Second source matrix or scalar.
    . @param dst Destination matrix that has the same size and number of channels as the input array(s).
    . The depth is defined by dtype or src1 depth.
    . @param scale Optional scale factor.
    . @param dtype Optional depth of the output array.
    . @param stream Stream for the asynchronous version.
    .   
    . This function, in contrast to divide, uses a round-down rounding mode.
    .   
    . @sa divide

```

Is there anything I’m missing on how to provide the scalar as a proper scalar to `cv2.cuda.divide`?

Please note that I could get around this issue using a constant matrix that acts as the scalar:

```auto
cu_test = cv2.cuda_GpuMat(4, 4, cv2.CV_8UC1, 16)
cu_fake_scalar = cv2.cuda_GpuMat(4, 4, cv2.CV_8UC1, 2)
cu_test = cv2.cuda.divide(cu_test, cu_fake_scalar)

```

However it seems inefficient when working with high resolution images.

I tested with Python 3.6.9 and OpenCV versions 4.5.4 and also 4.10.0.

Thanks in advance!  
Massimo

---

<div class="post-metadata">

**Author:** ![cudawarped](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@cudawarped](https://forum.opencv.org/u/cudawarped)\
**Post date:** [October 22, 2024, 7:30pm UTC](https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065/2 "2024-10-22T19:30:19Z")

</div>

All the functions which use a scalar in cudaarithm look like they need additional overloads. I’ll post a fix tomorrow.

---

<div class="post-metadata">

**Author:** ![cudawarped](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@cudawarped](https://forum.opencv.org/u/cudawarped)\
**Post date:** [October 23, 2024, 4:59pm UTC](https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065/3 "2024-10-23T16:59:07Z")

</div>

> [@cudawarped](#):
>
> I’ll post a fix tomorrow.

I haven’t had chance to submit a PR but the fix for divide is just a one liner. Add

```auto
CV_EXPORTS_W void inline divideWithScalar(InputArray src1, Scalar src2, OutputArray dst, double scale = 1, int dtype = -1, Stream& stream = Stream::Null()) {
    divide(src1, src2, dst, scale, dtype, stream);
}

```

underneath the existing defininition for divide

> <https://github.com/opencv/opencv_contrib/blob/80f1ca2442982ed518076cd88cf08c71155b30f6/modules/cudaarithm/include/opencv2/cudaarithm.hpp#L131>

Then you can call `divideWithScalar` instead of `divide`, see below.

```auto
cu_test = cv2.cuda_GpuMat(4, 4, cv2.CV_8UC1, 16)
test = cu_test.download()
print(test)
cu_test = cv2.cuda.divideScalar(cu_test, 2)
test = cu_test.download()
print(test)

```

For full fix see

> **[Comparing opencv:4.x...cudawarped:cuda\_fix\_python\_binaryop\_with\_scalar ·...](https://github.com/opencv/opencv_contrib/compare/4.x...cudawarped:opencv_contrib:cuda_fix_python_binaryop_with_scalar)**
>
> Repository for OpenCV's extra modules. Contribute to opencv/opencv\_contrib development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![cudawarped](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@cudawarped](https://forum.opencv.org/u/cudawarped)\
**Post date:** [October 24, 2024, 7:49am UTC](https://forum.opencv.org/t/python-cuda-operations-on-matrices-not-working-with-scalars/19065/4 "2024-10-24T07:49:37Z")

</div>

PR submited [`cudaarithm`: fix python bindings for binary ops involving scalars by cudawarped · Pull Request #3815 · opencv/opencv\_contrib · GitHub](https://github.com/opencv/opencv_contrib/pull/3815)
