As the CPU based SURF in opencv was very slow for realtime application, we decided to use GPU_SURF, after setting up the opencv_gpu we made the following code:
#include <iostream>
#include <iomanip>
#include <windows.h>
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/core/types_c.h"
using namespace std;
using namespace cv;
using namespace cv::gpu;
void help()
{
cout << "\nThis program demonstrates using SURF_GPU features detector, descriptor extractor and BruteForceMatcher_GPU" << endl;
cout << "\nUsage:\n\tmatcher_simple_gpu <image1> <image2>" << endl;
}
int main(int argc, char* argv[])
{
GpuMat img1(imread("C:\\OpenCV2.3\\opencv2.3\\bin\\Debug\\tsucuba_left.png", CV_LOAD_IMAGE_GRAYSCALE));
SURF_GPU surf;
// detecting keypoints & computing descriptors
GpuMat keypoints1GPU, keypoints2GPU;
GpuMat descriptors1GPU, descriptors2GPU;
surf(img1, GpuMat(), keypoints1GPU, descriptors1GPU);
cout << "FOUND " << keypoints1GPU.cols << " keypoints on first image" << endl;
//cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl;
CvCapture* capture = cvCreateCameraCapture(0);
int frame_width = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int frame_height = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
cout<<"frames done\n";
cv::gpu::GpuMat frame_gpu = cv::gpu::GpuMat(frame_width, frame_height, CV_8UC3);
cv::gpu::GpuMat frame_gpu_cvt = cv::gpu::GpuMat(frame_width, frame_height, CV_8UC1);
cout<<"gpu frmes loaded\n";
//Sleep(200);
while(cvGrabFrame(capture))
{
IplImage* frame;
frame =cvQueryFrame(capture);
CvMat* image=0;
image = cvCreateMat(frame->height, frame->width, CV_8UC1);
frame_gpu.upload(image);
cout<<"frame uploaded\n";
cvtColor(frame_gpu,frame_gpu_cvt,CV_RGB2GRAY);
cout<<"color done\n";
surf(frame_gpu_cvt, GpuMat(), keypoints2GPU, descriptors2GPU);
// matching descriptors
BruteForceMatcher_GPU< L2<float> > matcher;
GpuMat trainIdx, distance;
matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);
// downloading results
vector<KeyPoint> keypoints1, keypoints2;
vector<float> descriptors1, descriptors2;
vector<DMatch> matches;
surf.downloadKeypoints(keypoints1GPU, keypoints1);
surf.downloadKeypoints(keypoints2GPU, keypoints2);
surf.downloadDescriptors(descriptors1GPU, descriptors1);
surf.downloadDescriptors(descriptors2GPU, descriptors2);
BruteForceMatcher_GPU< L2<float> >::matchDownload(trainIdx, distance, matches);
// drawing the results
Mat img_matches;
drawMatches(img1, keypoints1, frame_gpu, keypoints2, matches, img_matches);
namedWindow("matches", 0);
imshow("matches", img_matches);
//waitKey(0);
}
return 0;
}
The error that comes on executing it is:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in unknown function, file
..\..\..\opencv_2.3\opencv\modules\gpu\src\color.cpp, line 186
It is due to the line:
cvtColor(frame_gpu,frame_gpu_cvt,CV_RGB2GRAY);
There maybe other errors, can someone please help us out on this one.
scnis the number of channels in the first argument tocvtColor. Converting from RGB to GRAY requires that the first argument has three or four channels. The lineframe_gpu.upload(image);is convertingframe_gputo one channel sinceimagehas one channel. It looks like you can skip the call tocvtColorand just callSURFdirectly onframe_gpu.