最近搞了个”机械臂+机器视觉”的项目,发现视觉这块用到的特征点匹配算法有点慢,因此有了用OpenCV的GPU模块来实现的想法。然而官网下载编译好的版本并没有这一块,而别人编译好的又少东西比较烦,因此决定自己来。
需要下载和安装的东西
编译过程
打开CMake
第一项选OpenCV源码文件夹,第二项选输出文件夹
注意,这里如果选择的是“Visual Studio 14 2015”,就是后面没带“Win64”的会报一堆CUDA相关的错误,这个应该是CUDA相关内容不支持win32造成的。我觉得x64才是未来,所以就没解决它,君若有想法可以研究下如何解决。
当然,即便是选择了Win64,我还是遇到了下面的错误:
就是“OpenCV2.4.13.3”文件夹下的CMakeLists.txt中的
`set(OPENCV_VCSVERSION "unknown")`
改为
set(OPENCV_VCSVERSION "2.4.13.3")
具体位置如下:
if(NOT GIT_RESULT EQUAL 0)
set(OPENCV_VCSVERSION "unknown")
endif()
else()
set(OPENCV_VCSVERSION "2.4.13.3")
endif()
一觉起来编译好了,用上,发现因为要把图像数据从内存拷贝到显存中,快不到哪去。。。额。。。
测试代码如下:
int num_devices = gpu::getCudaEnabledDeviceCount();//获取显卡数量
if (num_devices <=0)
{
printf("没有显卡");
return;
}
int enable_device_id = -1;//查找可以使用的显卡
for (size_t i = 0; i < num_devices; i++)
{
gpu::DeviceInfo dev_info(i);
if (dev_info.isCompatible())
{
enable_device_id = i;
}
}
if (enable_device_id < 0)
{
printf("没有可使用显卡");
return;
}
gpu::setDevice(enable_device_id);
Mat src_host = cv::imread("1.png", CV_LOAD_IMAGE_GRAYSCALE);
long begintime = clock();
gpu::GpuMat dst, src;
src.upload(src_host);
gpu::threshold(src, dst, 128.0, 255.0, CV_THRESH_BINARY);
Mat result_host;
dst.download(result_host);
printf("花费时间:%ds", clock() - begintime);
imshow("Result", result_host);
waitKey();
特征点匹配的代码如下:
Mat img1 = cv::imread("1.png", IMREAD_GRAYSCALE);
Mat img2 = cv::imread("2.png", IMREAD_GRAYSCALE);
long begintime = clock();
gpu::GpuMat gpuimg1, gpuimg2;
gpuimg1.upload(img1);
gpuimg2.upload(img2);
gpu::GpuMat keypoints_gpu_img1, keypoints_gpu_img2;
gpu::GpuMat descriptors_gpu_img1, descriptors_gpu_img2;
gpu::SURF_GPU surf(700);
surf(gpuimg1, gpu::GpuMat(), keypoints_gpu_img1, descriptors_gpu_img1);
surf(gpuimg2, gpu::GpuMat(), keypoints_gpu_img2, descriptors_gpu_img2);
std::vector<KeyPoint> keypoints_img1;
std::vector<KeyPoint> keypoints_img2;
surf.downloadKeypoints(keypoints_gpu_img1, keypoints_img1);
surf.downloadKeypoints(keypoints_gpu_img2, keypoints_img2);
std::vector<DMatch> matches;
gpu::BruteForceMatcher_GPU< L2<float> > matcher_lk;
matcher_lk.match(descriptors_gpu_img1, descriptors_gpu_img2, matches, gpu::GpuMat());
float max_distance = 0.2;
std::vector<DMatch> good_matches;
for (int i = 0; i < descriptors_gpu_img1.rows; i++) {
if (matches[i].distance < max_distance) {
good_matches.push_back(matches[i]);
}
}
Mat image_matches;
drawMatches(img1, keypoints_img1, img2, keypoints_img2, good_matches,
image_matches, Scalar(0, 255, 0), Scalar::all(-1), vector<char>(), 0);
printf("花费时间:%dms\n",clock()- begintime);
imshow("Gpu Surf", image_matches);
waitKey();