OpenCV CUDA ORB给出运行时错误,根本原因是什么,如何解决?

azpvetkf  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(133)

我正在尝试使用OpenCV查找ORB功能。当我直接传递图像时,我注意到特征往往位于图像的中心区域周围。为了避免这种情况,我将图像划分为网格,将每个网格视为一个小图像,然后在每个网格中找到特征,即每一个小形象。这样,特征不仅限于中心区域。
现在,为了加快速度,我决定使用OpenCV的CUDA implementation for ORB。非常方便的是,它的初始化与非CUDA版本相同:

static Ptr<ORB> cv::cuda::ORB::create (int   nfeatures = 500,
                                       float scaleFactor = 1.2f,
                                       int   nlevels = 8,
                                       int   edgeThreshold = 31,
                                       int   firstLevel = 0,
                                       int   WTA_K = 2,
                                       int   scoreType = ORB::HARRIS_SCORE,
                                       int   patchSize = 31,
                                       int   fastThreshold = 20,
                                       bool  blurForDescriptor = false 
                                      )

因此,我可以使用相同的参数值。此外,我不需要在代码中做太多的更改,我正在寻找功能:

for(ractangel_roi : list_of_rectangle_rois) {
    cv::Mat cpu_patch = big_image(rectangle_roi);
    cv::cuda::GpuMat gpu_patch;
    gpu_patch.upload(cpu_patch);
    orb_cuda->detectAndCompute(gpu_patch, cv::cuda::GpuMat(), key_point_vector, cv::cuda::GpuMat());
}

我没有得到任何编译错误,它运行的前几帧罚款。但是我总是得到这个运行时错误:

terminate called after throwing an instance of 'cv::Exception'
  what():  OpenCV(4.x.x) /tmp/opencv/modules/core/src/matrix_wrap.cpp:1659: error: (-215:Assertion failed) !fixedSize() in function 'release'

Aborted (core dumped

我试着玩不同的图像序列。但是在某些帧之后我得到相同的错误。
我怀疑它可能会耗尽GPU(CUDA)内存。因此,我在每次迭代后都编写了一段代码来检查CUDA内存总量和可用内存。但它从一开始就保持不变,直到它给出运行时错误。
根本原因是什么,如何修复此错误?

**注意:**如果我不将图像划分为网格并将整个图像转换为cv::cuda::GpuMat并将其传递给orb_cuda,则不会出现上述错误。
**编辑1:**我有多个不同的数据集,在某个帧上所有数据集都出现了这个错误。我的意思是帧编号因数据集而异,但当我一次又一次地运行代码时,它们保持一致。由于它发生在多个不同的帧(数据集不是公共的),我不能在这里分享它们。

von4xj4u

von4xj4u1#

我找到了解决方案(但不是100%确定它为什么有效)。
在我的应用程序中,我不需要担心特性描述符,所以在前面我使用detectAndCompute函数时,我传递的是空的GpuMat

orb_cuda->detectAndCompute(gpu_patch, cv::cuda::GpuMat(), key_point_vector, cv::cuda::GpuMat());

根据OpenCV文档,

virtual void cv::Feature2D::detectAndCompute (
    InputArray                image,
    InputArray                mask,
    std::vector< KeyPoint > & keypoints,
    OutputArray               descriptors,
    bool                      useProvidedKeypoints = false 
)

因此,如果我创建cv::cuda::GpuMat()的临时示例并传递该对象,而不是传递cv::cuda::GpuMat(),则不会得到错误:

cv::cuda::GpuMat gpu_descriptor_mat;
    orb_cuda->detectAndCompute(gpu_patch, cv::cuda::GpuMat(), key_point_vector, gpu_descriptor_mat);

我能想到的唯一一件事就是为什么上面的解决方案可以工作,对于descriptors,数据类型是OutputArray。这就是为什么我需要传递一个实际的cv::cuda::GpuMat()对象,而不是一个空对象。但我也不是100%确定。如果有人有更好的见解,如果你能在这里分享,将不胜感激。

相关问题