我一直在使用openvc将GPU特征描述符矩阵转换为CPU特征描述符矩阵时遇到一些问题,使用:
void downloadDescriptors(const GpuMat& descriptorsGPU, vector<float>& descriptors);
如您所见,此方法将包含描述符的GpuMat转换为包含它们的浮点数的向量。问题是,当我访问此向量的某个元素时,返回的值与预期的0
到255
的间隔大不相同。我制作了以下测试程序来比较提取时间和通过SURF_GPU
和SURF
获得的描述:
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
的元素,我希望获得0
和255
之间的值,就像我访问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)
我得到了类似描述符的结果,并且在匹配方面遇到了一些初步问题。我发现当描述符被下载到std::vector<float> 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 );