I've been having some problems with the conversion of a GPU feature descriptor matrix to a CPU feature descriptor matrix with openvc, using:
void downloadDescriptors(const GpuMat& descriptorsGPU, vector<float>& descriptors);
As you can see, this method converts the GpuMat holding the descriptors to a vector of floats holding them. The problem is, when I access some element of this vector, the values returned are quite different from the expected interval of 0
to 255
. I've made the following test program to compare the time of extraction and description obtained through SURF_GPU
and 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;
Checking the elements of descriptorsConverted
, I expected to get values between 0
and 255
, like I get when I access the elements of descriptorsCPU
. Instead, I got values like:
-0.000621859
0.000627841
-0.000503146
0.000543773
-8.69408e-05
0.000110254
0.000265697
0.000941789
0.0595061
0.0619723
I suspect this problem is related to the type returned by downloadDescriptors
, even though it's clear it returns a float vector.
I get similar results for the descriptors and had some initial trouble with matching. I've found that when the descriptors are downloaded to
std::vector<float> f_descriptors
that the length of the vector is divisible by the descriptor size (i.e., either 64 or 128) so I was able to use the following:Also, I found that uploading from the descriptorsGPU to descriptorsCPU also does the same thing and is probably safer: