In this section, we show two versions of the same program: one version uses the CPU to perform computations, and the other version uses the GPU. These two examples are called edgesCPU
and edgesGPU
, respectively, and allow us to point out the differences when using the GPU
module in OpenCV.
The edgesCPU
example is presented in the first place:
#include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; int main(int argc, char** argv){ if ( argc < 2 ){ std::cout << "Usage: ./edgesGPU <image>" << std::endl; return -1; } Mat orig = imread(argv[1]); Mat gray, dst; bilateralFilter(orig,dst,-1,50,7); cvtColor(dst,gray,COLOR_BGR2GRAY); Canny(gray,gray,7,20); imshow("Canny Filter", gray); waitKey(0); return 0; }
Now the edgesGPU
example is shown as follows:
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/gpu/gpu.hpp> using namespace cv; int main( int argc, char** argv){ if ( argc < 2 ){ std::cout << "Usage: ./edgesGPU <image>" << std::endl; return -1; } Mat orig = imread(argv[1]); gpu::GpuMat g_orig, g_gray, g_dst; //Transfer the image data to the GPU g_orig.upload(orig); gpu::bilateralFilter(g_orig,g_dst,-1,50,7); gpu::cvtColor(g_dst,g_gray,COLOR_BGR2GRAY); gpu::Canny(g_gray,g_gray,7,20); Mat dst; //Copy the image back to the CPU memory g_gray.download(dst); imshow("Canny Filter", dst); waitKey(0); return 0; }
The explanation of the code is given as follows. There are several differences in the previous examples, although they ultimately obtain the same result, as shown in the following screenshot. A new header file is added as the new data type and different implementations of the algorithms are used. #include <opencv2/gpu/gpu.hpp>
contains the GpuMat
data type, which is the basic container that stores images in the GPU memory. It also includes the specific GPU versions of the filter algorithms used in the second example.
An important consideration is that we need to transfer the images between the CPU and the GPU. This is achieved with the g_orig.upload(orig)
and g_gray.download(dst)
methods. Once the image is uploaded to the GPU, we can apply different operations to it that are executed on the GPU. In order to distinguish the version of the algorithm that needs to run, the gpu
namespace is used as in gpu::bilateralFilter
, gpu::cvtColor
, and gpu::Canny
. After the filters have been applied, the image is copied to the CPU memory again and displayed.
Regarding performance, the CPU version runs in 297 milliseconds, whereas the GPU version runs in just 18 milliseconds. In other words, the GPU version runs 16.5x faster.