Skip to content

Add python bindings to cudaobjdetect, cudawarping and cudaarithm #2396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 29, 2020
10 changes: 9 additions & 1 deletion modules/cudaarithm/include/opencv2/cudaarithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ CV_EXPORTS_W void bitwise_xor(InputArray src1, InputArray src2, OutputArray dst,
*/
CV_EXPORTS void rshift(InputArray src, Scalar_<int> val, OutputArray dst, Stream& stream = Stream::Null());

CV_EXPORTS_W inline void rshift(InputArray src, Scalar val, OutputArray dst, Stream& stream = Stream::Null()) {
rshift(src, Scalar_<int>(val), dst, stream);
}

/** @brief Performs pixel by pixel right left of an image by a constant value.

@param src Source matrix. Supports 1, 3 and 4 channels images with CV_8U , CV_16U or CV_32S
Expand All @@ -284,6 +288,10 @@ depth.
*/
CV_EXPORTS void lshift(InputArray src, Scalar_<int> val, OutputArray dst, Stream& stream = Stream::Null());

CV_EXPORTS_W inline void lshift(InputArray src, Scalar val, OutputArray dst, Stream& stream = Stream::Null()) {
lshift(src, Scalar_<int>(val), dst, stream);
}

/** @brief Computes the per-element minimum of two matrices (or a matrix and a scalar).

@param src1 First source matrix or scalar.
Expand Down Expand Up @@ -858,7 +866,7 @@ class CV_EXPORTS_W Convolution : public Algorithm
@param ccorr Flags to evaluate cross-correlation instead of convolution.
@param stream Stream for the asynchronous version.
*/
virtual void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr = false, Stream& stream = Stream::Null()) = 0;
CV_WRAP virtual void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr = false, Stream& stream = Stream::Null()) = 0;
};

/** @brief Creates implementation for cuda::Convolution .
Expand Down
178 changes: 178 additions & 0 deletions modules/cudaarithm/misc/python/test/test_cudaarithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/usr/bin/env python
import os
import cv2 as cv
import numpy as np

from tests_common import NewOpenCVTests, unittest

class cudaarithm_test(NewOpenCVTests):
def setUp(self):
super(cudaarithm_test, self).setUp()
if not cv.cuda.getCudaEnabledDeviceCount():
self.skipTest("No CUDA-capable device is detected")

def test_cudaarithm(self):
npMat = (np.random.random((128, 128, 3)) * 255).astype(np.uint8)

cuMat = cv.cuda_GpuMat(npMat)
cuMatDst = cv.cuda_GpuMat(cuMat.size(),cuMat.type())
cuMatB = cv.cuda_GpuMat(cuMat.size(),cv.CV_8UC1)
cuMatG = cv.cuda_GpuMat(cuMat.size(),cv.CV_8UC1)
cuMatR = cv.cuda_GpuMat(cuMat.size(),cv.CV_8UC1)

self.assertTrue(np.allclose(cv.cuda.merge(cv.cuda.split(cuMat)),npMat))

cv.cuda.split(cuMat,[cuMatB,cuMatG,cuMatR])
cv.cuda.merge([cuMatB,cuMatG,cuMatR],cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),npMat))

shift = (np.random.random((cuMat.channels(),)) * 8).astype(np.uint8).tolist()
self.assertTrue(np.allclose(cv.cuda.rshift(cuMat,shift).download(),npMat >> shift))
cv.cuda.rshift(cuMat,shift,cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),npMat >> shift))

self.assertTrue(np.allclose(cv.cuda.lshift(cuMat,shift).download(),(npMat << shift).astype('uint8')))
cv.cuda.lshift(cuMat,shift,cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),(npMat << shift).astype('uint8')))

def test_arithmetic(self):
npMat1 = np.random.random((128, 128, 3)) - 0.5
npMat2 = np.random.random((128, 128, 3)) - 0.5

cuMat1 = cv.cuda_GpuMat()
cuMat2 = cv.cuda_GpuMat()
cuMat1.upload(npMat1)
cuMat2.upload(npMat2)
cuMatDst = cv.cuda_GpuMat(cuMat1.size(),cuMat1.type())

self.assertTrue(np.allclose(cv.cuda.add(cuMat1, cuMat2).download(),
cv.add(npMat1, npMat2)))

cv.cuda.add(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.add(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.subtract(cuMat1, cuMat2).download(),
cv.subtract(npMat1, npMat2)))

cv.cuda.subtract(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.subtract(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.multiply(cuMat1, cuMat2).download(),
cv.multiply(npMat1, npMat2)))

cv.cuda.multiply(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.multiply(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.divide(cuMat1, cuMat2).download(),
cv.divide(npMat1, npMat2)))

cv.cuda.divide(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.divide(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.absdiff(cuMat1, cuMat2).download(),
cv.absdiff(npMat1, npMat2)))

cv.cuda.absdiff(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.absdiff(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.compare(cuMat1, cuMat2, cv.CMP_GE).download(),
cv.compare(npMat1, npMat2, cv.CMP_GE)))

cuMatDst1 = cv.cuda_GpuMat(cuMat1.size(),cv.CV_8UC3)
cv.cuda.compare(cuMat1, cuMat2, cv.CMP_GE, cuMatDst1)
self.assertTrue(np.allclose(cuMatDst1.download(),cv.compare(npMat1, npMat2, cv.CMP_GE)))

self.assertTrue(np.allclose(cv.cuda.abs(cuMat1).download(),
np.abs(npMat1)))

cv.cuda.abs(cuMat1, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),np.abs(npMat1)))

self.assertTrue(np.allclose(cv.cuda.sqrt(cv.cuda.sqr(cuMat1)).download(),
cv.cuda.abs(cuMat1).download()))

cv.cuda.sqr(cuMat1, cuMatDst)
cv.cuda.sqrt(cuMatDst, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.cuda.abs(cuMat1).download()))

self.assertTrue(np.allclose(cv.cuda.log(cv.cuda.exp(cuMat1)).download(),
npMat1))

cv.cuda.exp(cuMat1, cuMatDst)
cv.cuda.log(cuMatDst, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),npMat1))

self.assertTrue(np.allclose(cv.cuda.pow(cuMat1, 2).download(),
cv.pow(npMat1, 2)))

cv.cuda.pow(cuMat1, 2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.pow(npMat1, 2)))

def test_logical(self):
npMat1 = (np.random.random((128, 128)) * 255).astype(np.uint8)
npMat2 = (np.random.random((128, 128)) * 255).astype(np.uint8)

cuMat1 = cv.cuda_GpuMat()
cuMat2 = cv.cuda_GpuMat()
cuMat1.upload(npMat1)
cuMat2.upload(npMat2)
cuMatDst = cv.cuda_GpuMat(cuMat1.size(),cuMat1.type())

self.assertTrue(np.allclose(cv.cuda.bitwise_or(cuMat1, cuMat2).download(),
cv.bitwise_or(npMat1, npMat2)))

cv.cuda.bitwise_or(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.bitwise_or(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.bitwise_and(cuMat1, cuMat2).download(),
cv.bitwise_and(npMat1, npMat2)))

cv.cuda.bitwise_and(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.bitwise_and(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.bitwise_xor(cuMat1, cuMat2).download(),
cv.bitwise_xor(npMat1, npMat2)))

cv.cuda.bitwise_xor(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.bitwise_xor(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.bitwise_not(cuMat1).download(),
cv.bitwise_not(npMat1)))

cv.cuda.bitwise_not(cuMat1, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.bitwise_not(npMat1)))

self.assertTrue(np.allclose(cv.cuda.min(cuMat1, cuMat2).download(),
cv.min(npMat1, npMat2)))

cv.cuda.min(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.min(npMat1, npMat2)))

self.assertTrue(np.allclose(cv.cuda.max(cuMat1, cuMat2).download(),
cv.max(npMat1, npMat2)))

cv.cuda.max(cuMat1, cuMat2, cuMatDst)
self.assertTrue(np.allclose(cuMatDst.download(),cv.max(npMat1, npMat2)))

def test_convolution(self):
npMat = (np.random.random((128, 128)) * 255).astype(np.float32)
npDims = np.array(npMat.shape)
kernel = (np.random.random((3, 3)) * 1).astype(np.float32)
kernelDims = np.array(kernel.shape)
iS = (kernelDims/2).astype(int)
iE = npDims - kernelDims + iS

cuMat = cv.cuda_GpuMat(npMat)
cuKernel= cv.cuda_GpuMat(kernel)
cuMatDst = cv.cuda_GpuMat(tuple(npDims - kernelDims + 1), cuMat.type())
conv = cv.cuda.createConvolution()

self.assertTrue(np.allclose(conv.convolve(cuMat,cuKernel,ccorr=True).download(),
cv.filter2D(npMat,-1,kernel,anchor=(-1,-1))[iS[0]:iE[0]+1,iS[1]:iE[1]+1]))

conv.convolve(cuMat,cuKernel,cuMatDst,True)
self.assertTrue(np.allclose(cuMatDst.download(),
cv.filter2D(npMat,-1,kernel,anchor=(-1,-1))[iS[0]:iE[0]+1,iS[1]:iE[1]+1]))

if __name__ == '__main__':
NewOpenCVTests.bootstrap()
12 changes: 10 additions & 2 deletions modules/cudabgsegm/include/opencv2/cudabgsegm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ class CV_EXPORTS_W BackgroundSubtractorMOG : public cv::BackgroundSubtractor
CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0;

using cv::BackgroundSubtractor::getBackgroundImage;
CV_WRAP virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0;
virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0;

CV_WRAP inline void getBackgroundImage(CV_OUT GpuMat& backgroundImage, Stream& stream) {
getBackgroundImage(OutputArray(backgroundImage), stream);
}

CV_WRAP virtual int getHistory() const = 0;
CV_WRAP virtual void setHistory(int nframes) = 0;
Expand Down Expand Up @@ -131,7 +135,11 @@ class CV_EXPORTS_W BackgroundSubtractorMOG2 : public cv::BackgroundSubtractorMOG

CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0;

CV_WRAP virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0;
virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0;

CV_WRAP inline void getBackgroundImage(CV_OUT GpuMat &backgroundImage, Stream& stream) {
getBackgroundImage(OutputArray(backgroundImage), stream);
}
};

/** @brief Creates MOG2 Background Subtractor
Expand Down
37 changes: 37 additions & 0 deletions modules/cudabgsegm/misc/python/test/test_cudabgsegm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python
import os
import cv2 as cv
import numpy as np

from tests_common import NewOpenCVTests, unittest

class cudabgsegm_test(NewOpenCVTests):
def setUp(self):
super(cudabgsegm_test, self).setUp()
if not cv.cuda.getCudaEnabledDeviceCount():
self.skipTest("No CUDA-capable device is detected")

def test_cudabgsegm(self):
lr = 0.05
sz = (128,128,1)
npMat = (np.random.random(sz) * 255).astype(np.uint8)
cuMat = cv.cuda_GpuMat(npMat)
cuMatBg = cv.cuda_GpuMat(cuMat.size(),cuMat.type())
cuMatFg = cv.cuda_GpuMat(cuMat.size(),cuMat.type())

mog = cv.cuda.createBackgroundSubtractorMOG()
mog.apply(cuMat, lr, cv.cuda.Stream_Null(), cuMatFg)
mog.getBackgroundImage(cv.cuda.Stream_Null(),cuMatBg)
mog = cv.cuda.createBackgroundSubtractorMOG()
self.assertTrue(np.allclose(cuMatFg.download(),mog.apply(cuMat, lr, cv.cuda.Stream_Null()).download()))
self.assertTrue(np.allclose(cuMatBg.download(),mog.getBackgroundImage(cv.cuda.Stream_Null()).download()))

mog2 = cv.cuda.createBackgroundSubtractorMOG2()
mog2.apply(cuMat, lr, cv.cuda.Stream_Null(), cuMatFg)
mog2.getBackgroundImage(cv.cuda.Stream_Null(),cuMatBg)
mog2 = cv.cuda.createBackgroundSubtractorMOG2()
self.assertTrue(np.allclose(cuMatFg.download(),mog2.apply(cuMat, lr, cv.cuda.Stream_Null()).download()))
self.assertTrue(np.allclose(cuMatBg.download(),mog2.getBackgroundImage(cv.cuda.Stream_Null()).download()))

if __name__ == '__main__':
NewOpenCVTests.bootstrap()
55 changes: 55 additions & 0 deletions modules/cudacodec/misc/python/test/test_cudacodec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python
import os
import cv2 as cv
import numpy as np

from tests_common import NewOpenCVTests, unittest

class cudacodec_test(NewOpenCVTests):
def setUp(self):
super(cudacodec_test, self).setUp()
if not cv.cuda.getCudaEnabledDeviceCount():
self.skipTest("No CUDA-capable device is detected")

@unittest.skipIf('OPENCV_TEST_DATA_PATH' not in os.environ,
"OPENCV_TEST_DATA_PATH is not defined")
def test_reader(self):
#Test the functionality but not the results of the video reader

vid_path = os.environ['OPENCV_TEST_DATA_PATH'] + '/cv/video/1920x1080.avi'
try:
reader = cv.cudacodec.createVideoReader(vid_path)
ret, gpu_mat = reader.nextFrame()
self.assertTrue(ret)
self.assertTrue('GpuMat' in str(type(gpu_mat)), msg=type(gpu_mat))
#TODO: print(cv.utils.dumpInputArray(gpu_mat)) # - no support for GpuMat

# not checking output, therefore sepearate tests for different signatures is unecessary
ret, _gpu_mat2 = reader.nextFrame(gpu_mat)
#TODO: self.assertTrue(gpu_mat == gpu_mat2)
self.assertTrue(ret)
except cv.error as e:
notSupported = (e.code == cv.Error.StsNotImplemented or e.code == cv.Error.StsUnsupportedFormat or e.code == cv.Error.GPU_API_CALL_ERROR)
self.assertTrue(notSupported)
if e.code == cv.Error.StsNotImplemented:
self.skipTest("NVCUVID is not installed")
elif e.code == cv.Error.StsUnsupportedFormat:
self.skipTest("GPU hardware video decoder missing or video format not supported")
elif e.code == cv.Error.GPU_API_CALL_ERRROR:
self.skipTest("GPU hardware video decoder is missing")
else:
self.skipTest(e.err)

def test_writer_existence(self):
#Test at least the existence of wrapped functions for now

try:
_writer = cv.cudacodec.createVideoWriter("tmp", (128, 128), 30)
except cv.error as e:
self.assertEqual(e.code, cv.Error.StsNotImplemented)
self.skipTest("NVCUVENC is not installed")

self.assertTrue(True) #It is sufficient that no exceptions have been there

if __name__ == '__main__':
NewOpenCVTests.bootstrap()
44 changes: 44 additions & 0 deletions modules/cudafeatures2d/misc/python/test/test_cudafeatures2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python
import os
import cv2 as cv
import numpy as np

from tests_common import NewOpenCVTests, unittest

class cudafeatures2d_test(NewOpenCVTests):
def setUp(self):
super(cudafeatures2d_test, self).setUp()
if not cv.cuda.getCudaEnabledDeviceCount():
self.skipTest("No CUDA-capable device is detected")

def test_cudafeatures2d(self):
npMat1 = self.get_sample("samples/data/right01.jpg")
npMat2 = self.get_sample("samples/data/right02.jpg")

cuMat1 = cv.cuda_GpuMat()
cuMat2 = cv.cuda_GpuMat()
cuMat1.upload(npMat1)
cuMat2.upload(npMat2)

cuMat1 = cv.cuda.cvtColor(cuMat1, cv.COLOR_RGB2GRAY)
cuMat2 = cv.cuda.cvtColor(cuMat2, cv.COLOR_RGB2GRAY)

fast = cv.cuda_FastFeatureDetector.create()
_kps = fast.detectAsync(cuMat1)

orb = cv.cuda_ORB.create()
_kps1, descs1 = orb.detectAndComputeAsync(cuMat1, None)
_kps2, descs2 = orb.detectAndComputeAsync(cuMat2, None)

bf = cv.cuda_DescriptorMatcher.createBFMatcher(cv.NORM_HAMMING)
matches = bf.match(descs1, descs2)
self.assertGreater(len(matches), 0)
matches = bf.knnMatch(descs1, descs2, 2)
self.assertGreater(len(matches), 0)
matches = bf.radiusMatch(descs1, descs2, 0.1)
self.assertGreater(len(matches), 0)

self.assertTrue(True) #It is sufficient that no exceptions have been there

if __name__ == '__main__':
NewOpenCVTests.bootstrap()
Loading