2

I am very newbie on this topic and I need same simplified answers. I am trying to concat/merge images together in GPU by using cv2.cuda. I have understood that space needs to be allocate for new, merged image and then tiles can be placed by using CopyTo-function. I am not sure about the syntax how to do this correctly. Example with source 4 pics to be merged to 2 rows and two columns below. But this do not work like this. Can someone help with syntax or propose alternative method?

import cv2

gpu_image01 = cv2.cuda_GpuMat()
gpu_image02 = cv2.cuda_GpuMat()
gpu_image03 = cv2.cuda_GpuMat()
gpu_image04 = cv2.cuda_GpuMat()

image01 = cv2.imread('img1.png')
image02 = cv2.imread('img2.png')
image03 = cv2.imread('img3.png')
image04 = cv2.imread('img4.png')

gpu_image01.upload(image01)
gpu_image02.upload(image02)
gpu_image03.upload(image03)
gpu_image04.upload(image04)

new_image = cv2.cuda_GpuMat(2, 2)

new_image.copyTo(gpu_image01,(0,0))
new_image.copyTo(gpu_image02,(0,1))
new_image.copyTo(gpu_image03,(1,0))
new_image.copyTo(gpu_image04,(1,1))

result = new_image.download()

Error code from the provided example above:

TypeError: Expected Ptr<cv::cuda::GpuMat::Allocator> for argument 'allocator'

I have tried different ways without success. For example, if not try to specify matrix size, I get:

TypeError: Expected Ptr<cv::UMat> for argument 'mask'
talonmies
  • 70,661
  • 34
  • 192
  • 269
JanneI
  • 63
  • 5
  • `cv2.cuda_GpuMat(2, 2)` -- that's a 2x2 pixel matrix you've allocated. And the second parameter you're passing to `copyTo` doesn't make sense at all. Did you [read the documentation](https://docs.opencv.org/4.x/d0/d60/classcv_1_1cuda_1_1GpuMat.html)? – Dan Mašek Dec 21 '22 at 12:46
  • 1
    Hi Dan, Thanks for your reply. I have tried to read documentation + other sources. It is embarrassing but my understanding is limited. I am very beginning of my learning curve. If tiles are 100 x 50 pixels (w,h), perhaps following is closer but still wrong (getting: _TypeError: Expected Ptr for argument 'mask'_) `new_image = cv2.cuda_GpuMat((200, 100),gpu_image01.type()) new_image.copyTo(gpu_image01,(0,0)) new_image.copyTo(gpu_image02,(100,0)) new_image.copyTo(gpu_image03,(0,50))` – JanneI Dec 21 '22 at 13:27
  • OK, so first things first. Looks like your assumption is that `image01`..`image04` are the same size, correct? Then after you load those images, you should have some code to verify that's the case, and raise an error if it's not. When you've done that, store height and width of one of them to variables, to use later. | Next you need to allocate an appropriate size destination `GpuMat` -- the appropriate size in this case would be twice the height and twice the width of one of the input images. You also need to specify the appropriate data type -- again should be the same as the input. – Dan Mašek Dec 21 '22 at 13:28
  • Next, you have the source and destination swapped in your calls to `copyTo`. For example, you want to copy pixels from `gpu_image01` to `new_image`, not the other way around. So those lines should looke like `gpu_image01.copyTo(something)`. Now, what should that "something" be? First of all, the source and destination should be the same shape. However, that's not the case -- `new_image` is twice the size. You need to create a view of `new_image` that matches the size of the inputs. You can use `rowRange` and `colRange` methods to accomplish this. – Dan Mašek Dec 21 '22 at 13:34
  • So the first copy statement might look like: `gpu_image01.copyTo(new_image.rowRange(0, in_height).colRange(0, in_width))`. I don't have Cuda enabled version of OpenCV to try it with tho. Hopefully this can point you on the right track. – Dan Mašek Dec 21 '22 at 13:36
  • 1
    Dan. I got it working. I love you man; you are my superhero! – JanneI Dec 21 '22 at 14:58
  • Glad it helped :) Since you've done most of the work, why don't you self-answer your question... – Dan Mašek Dec 22 '22 at 01:58

1 Answers1

0

As suggested in comments, here is the answer to my question reflecting the example parameters.

import cv2

gpu_image01 = cv2.cuda_GpuMat()
gpu_image02 = cv2.cuda_GpuMat()
gpu_image03 = cv2.cuda_GpuMat()
gpu_image04 = cv2.cuda_GpuMat()

image01 = cv2.imread('img1.png')
image02 = cv2.imread('img2.png')
image03 = cv2.imread('img3.png')
image04 = cv2.imread('img4.png')

gpu_image01.upload(image01)
gpu_image02.upload(image02)
gpu_image03.upload(image03)
gpu_image04.upload(image04)

new_image = cv2.cuda_GpuMat((200,100),gpu_image_resized_01.type())

gpu_image01.copyTo(new_image.rowRange(0, 50).colRange(0, 100))
gpu_image02.copyTo(new_image.rowRange(0, 50).colRange(100, 200))
gpu_image03.copyTo(new_image.rowRange(50, 100).colRange(0, 100))
gpu_image04.copyTo(new_image.rowRange(50, 100).colRange(100, 200))

result = new_image.download()
JanneI
  • 63
  • 5