OpenGL texture to GpuMat (CUDA)?

Find and replace. See

1 Like

Thank you @cudawarped for going to the trouble of creating those commits

I have manually downloaded the 3 files from the commits, and I had to add CV_WRAP to

    CV_WRAP cuda::GpuMat mapDevice();
    CV_WRAP void unmapDevice();

in opengl.hpp as downloaded from the commits… OpenCV builds successfully in Visual Studio, but when trying to mapDevice(), this happens:

Traceback (most recent call last):
File “C:\Users\fdasfasdfasd\Documents\test.py”, line 48, in
openglcudamat = oglbuf.mapDevice()
cv2.error: OpenCV(4.10.0) C:\opencv-4.10.0\modules\core\src\opengl.cpp:182: error: (-217:Gpu API call) invalid resource handle in function ‘`anonymous-namespace’::CudaResource::registerBuffer’

the specific line in opengl.cpp:
cudaSafeCall( cudaGraphicsGLRegisterBuffer(&resource, buffer, cudaGraphicsMapFlagsNone) );

Well that’s certainly interesting…

Can you share a MRE?

The test for mapDevice()

which doesn’t use an external OpenGL array works in python. e.g.


# cv::namedWindow("test", cv::WINDOW_OPENGL);
cv.namedWindow("test", cv.WINDOW_OPENGL)
# cv::Mat gold = randomMat(size, type);
gold = np.random.rand(10,10)
# cv::ogl::Buffer buf(gold, cv::ogl::ARRAY_BUFFER, true);
buf = cv.ogl_Buffer(gold,cv.ogl.ARRAY_BUFFER,True)
# cv::cuda::GpuMat dst = buf.mapDevice();
dst = buf.mapDevice()
# cv::destroyAllWindows();
cv.destroyAllWindows()

np.testing.assert_array_equal(dst.download(), gold)
import numpy as np
from OpenGL.GL import *
import cv2

import pygame

height = 480
width = 640

#pygame
#-----------------------

pygame.init()
pygame.display.set_caption('Texture Receiver Example')
pygame.display.set_mode((width, height),
                        pygame.OPENGL | pygame.DOUBLEBUF)
#-----------------------
cv2.cuda.setDevice(0)
cudastream1 = cv2.cuda.Stream()
TextureID = glGenTextures(1)

glBindTexture(GL_TEXTURE_2D, TextureID)


pbo = glGenBuffers(1) # create a pixel buffer object
openglframe =np.random.randint(low=0,high=255,size=(height,width,4)) # array with the resolution of the image I want to use, in 4 channels for RGBA, used for the byte size of glBufferData
print(openglframe)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo)
glBufferData(GL_PIXEL_PACK_BUFFER,openglframe ,  GL_DYNAMIC_READ)  # configures the pixel buffer

openglcudamat = cv2.cuda.GpuMat(int(height),width,cv2.CV_8UC4) # temporary texture used for mapping the address from OpenGL as a CUDA GpuMat
outputcudamat = cv2.cuda.GpuMat(height,width,cv2.CV_8UC4) # the OpenGL texture should end up as this CUDA GpuMat


glActiveTexture(GL_TEXTURE0) # activate the OpenGL texture slot
glBindTexture(GL_TEXTURE_2D, TextureID) # selects the texture

glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, openglframe) # Load the image into OpenGL

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo) #selects the pixel buffer
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,0)


# After this is the Python part

oglbuf = cv2.ogl.Buffer(int(height),int(width),cv2.CV_8UC4,pbo)
print("test")
openglcudamat = oglbuf.mapDevice()
openglcudamat.copyTo(outputcudamat)

test=outputcudamat.download()


print(test)
cv2.imshow("test", test)