【问题标题】:Problems with opencv feature descriptors converted from gpu feature descriptors从gpu特征描述符转换的opencv特征描述符的问题
【发布时间】:2012-05-30 06:54:38
【问题描述】:

我在使用 openvc 将 GPU 特征描述符矩阵转换为 CPU 特征描述符矩阵时遇到了一些问题,使用:

void downloadDescriptors(const GpuMat& descriptorsGPU, vector<float>& descriptors);

如您所见,此方法将保存描述符的 GpuMat 转换为保存它们的浮点向量。问题是,当我访问这个向量的某个元素时,返回的值与0255 的预期区间完全不同。我做了如下测试程序,比较通过SURF_GPUSURF得到的提取时间和描述:

clock_t start;
clock_t end;

SURF_GPU surfGPU;
SURF surf;

Mat img1 = imread("Ipo_SP_01.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat outimageGPU;
Mat outimageCPU;
GpuMat imgGPU;
imgGPU.upload(img1);

vector<KeyPoint> keyp_A;
vector<KeyPoint> keyp_B;
GpuMat keypGPU;

vector<float> descriptorsConverted;
Mat descriptorsCPU;
GpuMat descriptorsGPU;

start = (clock() * 1000)/CLOCKS_PER_SEC;
surfGPU(imgGPU, GpuMat(), keypGPU, descriptorsGPU);
end = (clock() * 1000)/CLOCKS_PER_SEC;
cout << "GPU time: " << end - start << endl;
surfGPU.downloadKeypoints(keypGPU, keyp_A);
surfGPU.downloadDescriptors(descriptorsGPU, descriptorsConverted);
cout << "GPU Keypoints = " << keyp_A.size() << endl;

start = (clock() * 1000)/CLOCKS_PER_SEC;
surf(img1, Mat(), keyp_B, descriptorsCPU);
end = (clock() * 1000)/CLOCKS_PER_SEC;
cout << "CPU time: " << end - start << endl;
cout << "CPU Keypoints = " << keyp_B.size() << endl;

drawKeypoints(img1, keyp_A, outimageGPU, Scalar(255, 255, 255), DrawMatchesFlags::DEFAULT);
imwrite("GPU.jpg", outimageGPU);
drawKeypoints(img1, keyp_B, outimageCPU, Scalar(255, 255, 255), DrawMatchesFlags::DEFAULT);
imwrite("CPU.jpg", outimageCPU);

return 0;

检查descriptorsConverted 的元素,我希望得到0255 之间的值,就像我访问descriptorsCPU 的元素时一样。相反,我得到了如下值:

-0.000621859
0.000627841
-0.000503146
0.000543773
-8.69408e-05
0.000110254
0.000265697
0.000941789
0.0595061
0.0619723

我怀疑这个问题与downloadDescriptors 返回的类型有关,尽管很明显它返回了一个浮点向量。

【问题讨论】:

  • 我的猜测是该值在浮点数的 0 和 1 之间进行了归一化( - 可能是舍入错误)。您是否尝试乘以 255 并四舍五入(比较)?
  • 我确实做到了。这些值仍然很奇怪,主要是因为有负数和正数。此外,大多数值乘以 255 后仍介于 0 和 1 之间,并且会四舍五入为 0。
  • 是否所有的负值都四舍五入为零?对于其他值,您是否注意到浮点版本(缩放到 255)的 0 比 CPU 版本多得多?我认为在 SURF 描述符中有许多零是正常的。
  • 我还没有尝试对值进行四舍五入,但检查一些结果,我可以确认其中许多会四舍五入为 0,而使用 CPU Surf 我通常在描述符中根本没有 0 .
  • 您是否尝试使用 'single(T)' 或 'double(T)' 方法强制将描述符 GPU 转换为另一种类型,然后通过 downloadDescriptors 进行转换?也许该方法期望某种类型,但内部没有进行转换,也没有提及。

标签: c++ opencv gpu surf feature-descriptor


【解决方案1】:

我得到了类似的描述符结果,并且在匹配时遇到了一些初始问题。我发现当描述符下载到 std::vector&lt;float&gt; f_descriptors 时,向量的长度可以被描述符大小(即 64 或 128)整除,因此我可以使用以下内容:

std::vector<float> f_descriptors;
std::vector<cv::KeyPoint> keypoints;
surfGPU( imgGPU, cv::gpu::GpuMat(), keypoints, f_descriptors  );
descriptorsCPU = cv::Mat( (int)f_descriptors.size()/surfGPU.descriptorSize(), surfGPU.descriptorSize(), CV_32F, f_descriptors[0] );

另外,我发现从descriptorsGPU上传到descriptorsCPU也可以做同样的事情,而且可能更安全:

std::vector<cv::KeyPoint> keypoints;
cv::gpu::GpuMat descriptorsGPU
surfGPU( imgGPU, cv::gpu::GpuMat(), keypoints, descriptorsGPU  );
descriptorsGPU.download( descriptorsCPU );

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 2013-01-01
    • 1970-01-01
    • 2014-05-15
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多