Feature Extraction CUDA/PYTHON

Hello, I’m quite new to cuda, I need to find the characteristic points between two successive images and I don’t know how to do it, I have 4 images and I need to extract the characteristic points of the image 0.png in 1.png, search for those points features of 1.png in 2.png and so on (a visual odometry algorithm), and I get the following error, can someone help me


import cv2 as cv

img_files = ['0.png', '1.png', '2.png', '3.png']
orb = cv.cuda.ORB_create(5000)
matcherGPU = cv.cuda.DescriptorMatcher_createBFMatcher(cv.NORM_HAMMING) 

gpu_frame = cv.cuda_GpuMat()

for i in range(len(img_files)):
    screenshot = cv.imread(f"C:\\Users\\Geddy\\Desktop\\{img_files[i]}")
    gpu_frame.upload(screenshot)  
    screenshot = cv.cuda.cvtColor(gpu_frame, cv.COLOR_RGB2BGR)
    
    kp1, des1 = orb.detectAndComputeAsync(screenshot[i-1], None)
    kp2, des2 = orb.detectAndComputeAsync(screenshot[i], None)
    
    matches = matcherGPU.knnMatch(des1,des2, k=2)
    # download image from GPU (cv2.cuda_GpuMat -> numpy.ndarray)
    screenshot = screenshot.download()

Traceback (most recent call last):
  File "c:\Users\Geddy\Desktop\test2.py", line 20, in <module>
    kp1, des1 = orb.detectAndComputeAsync(screenshot[i-1], None) # Both are returned as GPU Mats
TypeError: 'cv2.cuda.GpuMat' object is not subscriptable

A GpuMat is an OpenCV object which can only be accessed using OpenCV api functions, your confusing it with a numpy array, pytorch tensor etc. If you want to access a single color plane then you will need to split it first

or if you just want to process the grey level frame cvtColor to grey

Hello, thanks for your reply, what I want is to extract the characteristics of different images and do the matching (it is a visual odometry algorithm), I want to know how to do this algorithm with different images, not only with 2 (it is easy with 2) , the problem is when I want to do it with different images, suppose I have 10 images (a sequence of the KITTI dataset), I need to search the characteristics of image 1, with 2, then 2 with 3, 3 with 4 and so on, below I put an example with 2 images that works, but I don’t know how to do it for several images

from distutils.command.upload import upload
import cv2
import numpy as np

        
MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15
        # load images into numpy
npMat1 = cv2.imread("C:\\Users\\Geddy\\OneDrive\\Desktop\\0.png")
npMat2 = cv2.imread("C:\\Users\\Geddy\\OneDrive\\Desktop\\1.png")      
        # upload into Cuda
cuMat1 = cv2.cuda_GpuMat()
cuMat2 = cv2.cuda_GpuMat()
cuMat1.upload(npMat1)
cuMat2.upload(npMat2)        
        #convert to Gray
cuMat1g = cv2.cuda.cvtColor(cuMat1, cv2.COLOR_RGB2GRAY)
cuMat2g = cv2.cuda.cvtColor(cuMat2, cv2.COLOR_RGB2GRAY)
        #ORB
corb = cv2.cuda_ORB.create(MAX_FEATURES)
_kps1, _descs1 = corb.detectAndComputeAsync(cuMat1g, None)
_kps2, _descs2 = corb.detectAndComputeAsync(cuMat2g, None)
        #convert Keypoints to CPU
kps1 = [cv2.KeyPoint() for i in range(MAX_FEATURES)]
kps2 = [cv2.KeyPoint() for i in range(MAX_FEATURES)]
corb.convert(_kps1)
corb.convert(_kps2)      
        # Matching
cbf = cv2.cuda_DescriptorMatcher.createBFMatcher(cv2.NORM_HAMMING)
cmatches = cbf.match(_descs1, _descs2) 
        # Sort matches by score
cmatches=sorted(cmatches, key=lambda x: x.distance, reverse=False)
        # Remove not so good matches
numGoodMatches = int(len(cmatches) * GOOD_MATCH_PERCENT)
cmatches = cmatches[:numGoodMatches]  
        # Draw top matches
imMatches = cv2.drawMatches(npMat1, kps1, npMat2, kps2, cmatches, None)
cv2.imwrite("gpu_matches.jpg", imMatches)

It is easy to create a GPU_MATH type variable, because it would be 2 images, but when there are 200 images, what do I do? could you call the upload function and upload 200 images? or do I have to upload image by image (as shown in the example)?

You can do either but I would recommend uploading the images just before you use them to avoid using a lot of GPU memory.

Thank you very much, even so I have no idea how to do it, I would have an array type variable that would contain the 10 images, I would create a variable cuMat1 = cv2.cuda_GpuMat() and then I would have to load those 10 images, I have no idea there How to do it, I don’t know if I have to create a cuMat1 = cv2.cuda_GpuMat() for each of the images (as in the previous example, 2 are created because there are 2 images). Example:

npMat1 = cv2.imread("C:\\Users\\Geddy\\OneDrive\\Desktop\\*.png") #list of 10 images
cuMat1 = cv2.cuda_GpuMat()
cuMat1.upload(npMat1)

This is not working, and if I put everything inside a for it doesn’t work either, so it generates the following question: is it possible to create a single variable cuMat1 = cv2.cuda_GpuMat() and then when the function cuMat1.upload(npMat1 ), load an array (because the variable contains 10 images)? Or would it be necessary to create a cuMat1 = cv2.cuda_GpuMat() for each of the images?

You need to get a list of all the images then iterate over it uploading each one individually. I think this is more of a python question than an OpenCV one.

imread() only reads a single image, not a list of images.

if you want to do that, use e.g. glob.glob(directory) to get a list of filenames, then imread() those one by one.

Sorry for my mistake, I know that imread is only for an image I just wanted to exemplify what I would like to do, I will try to upload image by image to see if it works